From 882c632bc50211ee424b54b1ff7b1d8813e39abf Mon Sep 17 00:00:00 2001 From: Sascha Lisson Date: Sat, 9 Dec 2023 08:19:11 +0100 Subject: [PATCH] copied original Java files of the sync plugin from MPS As a separate commit so that we have a history of the changes that were required after copying the files from MPS. --- .../reflection/runtime/ReflectionUtil.java | 59 + .../org/modelix/common/AuthorOverride.java | 25 + .../org/modelix/common/InstanceJwtToken.java | 8 + .../org/modelix/common/PropertyOrEnv.java | 31 + .../main/java/org/modelix/common/trace.info | 90 + .../modelix/model/mpsadapters/mps/ANode.java | 368 + .../model/mpsadapters/mps/ANodeReference.java | 41 + .../model/mpsadapters/mps/AReference.java | 78 + .../mps/BootstrapConceptMappings.java | 110 + .../mps/DevKitDependencyAsNode.java | 321 + .../model/mpsadapters/mps/DummyConcept.java | 98 + .../model/mpsadapters/mps/DummySNodeId.java | 12 + .../model/mpsadapters/mps/EModelMode.java | 9 + .../mps/JavaModuleFacetAsNode.java | 187 + .../model/mpsadapters/mps/MPSArea.java | 199 + .../mps/MPSLanguageRepository.java | 64 + .../mpsadapters/mps/ModelImportAsNode.java | 147 + .../mps/ModuleDependencyAsNode.java | 278 + .../mpsadapters/mps/NodeToSModelAdapter.java | 198 + .../mpsadapters/mps/NodeToSModuleAdapter.java | 136 + .../mpsadapters/mps/NodeToSNodeAdapter.java | 718 ++ .../model/mpsadapters/mps/ProjectAsNode.java | 168 + .../mpsadapters/mps/ProjectModuleAsNode.java | 160 + .../mps/ReadOnlyPropertyAccessor.java | 11 + .../mpsadapters/mps/SConceptAdapter.java | 267 + .../mps/SContainmentLinkAdapter.java | 87 + .../mpsadapters/mps/SLanguageAdapter.java | 68 + .../model/mpsadapters/mps/SModelAsNode.java | 299 + .../model/mpsadapters/mps/SModuleAsNode.java | 451 + .../model/mpsadapters/mps/SNodeAPI.java | 184 + .../mps/SNodeReferenceAdapter.java | 55 + .../mpsadapters/mps/SNodeToNodeAdapter.java | 392 + .../mpsadapters/mps/SPropertyAdapter.java | 67 + .../mps/SReferenceLinkAdapter.java | 73 + .../mpsadapters/mps/SRepositoryAsNode.java | 168 + .../mps/SingleLanguageDependencyAsNode.java | 329 + .../mpsadapters/mps/TreeElementAsNode.java | 278 + .../modelix/model/mpsadapters/mps/trace.info | 6719 +++++++++++++ .../ApplicationPlugin_AppPluginPart.java | 23 + .../plugin/MPSNodeReferenceSerializer.java | 78 + .../plugin/Mpsadapters_ApplicationPlugin.java | 26 + .../model/mpsadapters/plugin/trace.info | 122 + .../org/modelix/model/mpsplugin/Binding.java | 348 + .../model/mpsplugin/CloudDataDependency.java | 12 + .../modelix/model/mpsplugin/CloudIcons.java | 19 + .../CloudNodeTreeNodeCreationMethods.java | 49 + .../model/mpsplugin/CloudRepository.java | 373 + .../model/mpsplugin/CloudTransientModel.java | 112 + .../model/mpsplugin/CloudTransientModule.java | 50 + .../mpsplugin/CloudTransientModules.java | 105 + .../model/mpsplugin/CommandHelper.java | 123 + .../modelix/model/mpsplugin/ELockType.java | 11 + .../model/mpsplugin/ForeignNodeReference.java | 124 + .../model/mpsplugin/ICloudRepository.java | 14 + .../modelix/model/mpsplugin/INodeUtils.java | 164 + .../model/mpsplugin/IUserObjectContainer.java | 9 + .../model/mpsplugin/IterableOfINodeUtils.java | 28 + .../model/mpsplugin/LetterInSquareIcon.java | 53 + .../model/mpsplugin/MPSNodeMapping.java | 25 + .../model/mpsplugin/MPSProjectUtils.java | 59 + .../model/mpsplugin/MessageHandler.java | 10 + .../mpsplugin/MetaModelSynchronizer.java | 7 + .../modelix/model/mpsplugin/ModelAccess.java | 33 + .../modelix/model/mpsplugin/ModelBinding.java | 520 + .../model/mpsplugin/ModelCloudExporter.java | 442 + .../mpsplugin/ModelCloudImportUtils.java | 245 + .../ModelPersistenceWithFixedId.java | 91 + .../ModelPropertiesSynchronizer.java | 415 + .../mpsplugin/ModelServerConnection.java | 614 ++ .../mpsplugin/ModelServerConnections.java | 225 + .../mpsplugin/ModelServerNavigation.java | 45 + .../model/mpsplugin/ModelSynchronizer.java | 708 ++ .../model/mpsplugin/ModelixNotifications.java | 23 + .../model/mpsplugin/ModelsSynchronizer.java | 136 + .../model/mpsplugin/ModuleBinding.java | 170 + .../model/mpsplugin/ModuleCheckout.java | 55 + .../modelix/model/mpsplugin/ModuleUtils.java | 24 + .../mpsplugin/MpsReplicatedRepository.java | 140 + .../org/modelix/model/mpsplugin/NodeMap.java | 165 + .../model/mpsplugin/NonIndirectBranch.java | 32 + .../PNodeAdapterCreationMethods.java | 55 + .../PhysicalToCloudModelMapping.java | 27 + .../model/mpsplugin/ProjectBinding.java | 215 + .../model/mpsplugin/ProjectModuleBinding.java | 20 + .../mpsplugin/ProjectModulesSynchronizer.java | 148 + .../modelix/model/mpsplugin/RootBinding.java | 108 + .../modelix/model/mpsplugin/SModelUtils.java | 42 + .../modelix/model/mpsplugin/SModuleUtils.java | 49 + .../model/mpsplugin/SharedExecutors.java | 37 + .../model/mpsplugin/SyncDirection.java | 9 + .../modelix/model/mpsplugin/SyncQueue.java | 308 + .../org/modelix/model/mpsplugin/SyncTask.java | 92 + .../modelix/model/mpsplugin/Synchronizer.java | 92 + .../model/mpsplugin/TestCloudRepository.java | 32 + .../model/mpsplugin/TransactionUtil.java | 99 + .../TransientModelsSynchronizer.java | 26 + .../mpsplugin/TransientModuleBinding.java | 87 + .../mpsplugin/TreeChangeMulticaster.java | 61 + .../model/mpsplugin/TreeChangesCollector.java | 65 + .../model/mpsplugin/UserObjectKey.java | 36 + .../model/mpsplugin/WriteAccessUtil.java | 26 + .../modelix/model/mpsplugin/_Adapters.java | 17 + .../history/CloudBindingTreeNode.java | 106 + .../history/CloudBranchTreeNode.java | 56 + .../mpsplugin/history/CloudNodeTreeNode.java | 249 + .../history/CloudNodeTreeNodeBinding.java | 42 + .../CloudNodeTreeNodeClassification.java | 42 + .../mpsplugin/history/CloudRootTreeNode.java | 61 + .../model/mpsplugin/history/CloudView.java | 88 + .../model/mpsplugin/history/HistoryView.java | 191 + .../model/mpsplugin/history/LoadingIcon.java | 106 + .../history/ModelServerTreeNode.java | 184 + .../mpsplugin/history/RepositoryTreeNode.java | 160 + .../mpsplugin/history/TreeModelUtil.java | 121 + .../mpsplugin/history/TreeNodeAccess.java | 78 + .../mpsplugin/history/TreeNodeBinding.java | 33 + .../history/TreeNodeClassification.java | 50 + .../model/mpsplugin/history/_Adapters.java | 17 + .../model/mpsplugin/history/trace.info | 1728 ++++ .../mpsplugin/plugin/AddBranch_Action.java | 110 + .../mpsplugin/plugin/AddChildNode_Action.java | 135 + .../mpsplugin/plugin/AddModelNode_Action.java | 69 + .../plugin/AddModelServer_Action.java | 82 + .../plugin/AddModuleNode_Action.java | 69 + .../plugin/AddProjectBinding_Action.java | 105 + .../plugin/AddProjectNode_Action.java | 69 + .../plugin/AddRepository_Action.java | 69 + .../AddTransientModuleBinding_Action.java | 78 + .../ApplicationPlugin_AppPluginPart.java | 129 + .../model/mpsplugin/plugin/AutoBindings.java | 301 + .../plugin/CheckoutAndSyncModule_Action.java | 61 + .../plugin/CheckoutModule_Action.java | 69 + ...ysicalModulesCloudActions_ActionGroup.java | 47 + ...ActionsForPhysicalModules_ActionGroup.java | 30 + ...sicalProjectsCloudActions_ActionGroup.java | 52 + ...ctionsForPhysicalProjects_ActionGroup.java | 30 + .../plugin/CloudBindingGroup_ActionGroup.java | 18 + .../plugin/CloudBranchGroup_ActionGroup.java | 20 + .../plugin/CloudHistoryTool_Tool.java | 35 + .../CloudNodeGroupAddChild_ActionGroup.java | 120 + ...CloudNodeGroupSetProperty_ActionGroup.java | 77 + .../plugin/CloudNodeGroup_ActionGroup.java | 54 + .../CloudResourcesConfigurationComponent.java | 89 + .../plugin/CloudRootGroup_ActionGroup.java | 18 + .../mpsplugin/plugin/CloudTool_Tool.java | 28 + ...pyAndSyncPhysicalModuleOnCloud_Action.java | 91 + ...yAndSyncPhysicalProjectOnCloud_Action.java | 87 + .../CopyPhysicalModuleOnCloud_Action.java | 91 + .../mpsplugin/plugin/DeleteModule_Action.java | 64 + .../plugin/DeleteProject_Action.java | 64 + .../plugin/EModelixExecutionMode.java | 13 + .../plugin/GetCloudRepositorySize_Action.java | 71 + .../model/mpsplugin/plugin/IconContainer.java | 11 + .../plugin/LoadHistoryForBranch_Action.java | 96 + .../LoadHistoryForRepository_Action.java | 62 + .../plugin/MetaMetaModelMappings.java | 49 + .../mpsplugin/plugin/ModelImportExport.java | 367 + .../plugin/ModelServerGroup_ActionGroup.java | 21 + .../ModelixConfigurationSystemProperties.java | 54 + .../plugin/ModelixExportConfiguration.java | 20 + .../plugin/ModelixImportConfiguration.java | 17 + .../plugin/ModuleAlreadyOnCloud_Action.java | 82 + .../plugin/Mpsplugin_ApplicationPlugin.java | 74 + .../plugin/Mpsplugin_ProjectPlugin.java | 25 + .../plugin/NavigateToMpsNode_Action.java | 169 + .../plugin/PersistedBindingConfiguration.java | 465 + .../mpsplugin/plugin/ProjectMakeRunner.java | 156 + .../plugin/ProjectManagerExtensions.java | 34 + .../ProjectPlugin_ProjectPluginPart.java | 45 + .../mpsplugin/plugin/Reconnect_Action.java | 65 + .../plugin/RemoveModelServer_Action.java | 69 + .../plugin/RemoveRepository_Action.java | 47 + .../RemoveTransientModuleBinding_Action.java | 75 + .../plugin/RepositoryGroup_ActionGroup.java | 20 + .../mpsplugin/plugin/SetProperty_Action.java | 118 + .../plugin/ShowAuthenticationInfo_Action.java | 64 + .../plugin/ShowProperties_Action.java | 90 + .../plugin/ShowReferences_Action.java | 102 + .../plugin/StoreAllModules_Action.java | 174 + .../mpsplugin/plugin/SwitchBranch_Action.java | 53 + .../model/mpsplugin/plugin/TextIcon_1.png | Bin 0 -> 259 bytes .../model/mpsplugin/plugin/TextIcon_13262.png | Bin 0 -> 186 bytes .../model/mpsplugin/plugin/Unbind_Action.java | 74 + .../model/mpsplugin/plugin/_Adapters.java | 18 + .../modelix/model/mpsplugin/plugin/trace.info | 5686 +++++++++++ .../projectview/CloudModuleTreeNode.java | 92 + .../CloudProjectViewExtension.java | 312 + .../model/mpsplugin/projectview/trace.info | 483 + .../org/modelix/model/mpsplugin/trace.info | 8753 +++++++++++++++++ 189 files changed, 44430 insertions(+) create mode 100644 mps-legacy-sync-plugin/src/main/java/de/slisson/mps/reflection/runtime/ReflectionUtil.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/common/AuthorOverride.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/common/InstanceJwtToken.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/common/PropertyOrEnv.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/common/trace.info create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ANode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ANodeReference.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/AReference.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/BootstrapConceptMappings.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DevKitDependencyAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DummyConcept.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DummySNodeId.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/EModelMode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/JavaModuleFacetAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/MPSArea.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/MPSLanguageRepository.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ModelImportAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ModuleDependencyAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSModelAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSModuleAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSNodeAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ProjectAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ProjectModuleAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ReadOnlyPropertyAccessor.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SConceptAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SContainmentLinkAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SLanguageAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SModelAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SModuleAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeAPI.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeReferenceAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeToNodeAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SPropertyAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SReferenceLinkAdapter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SRepositoryAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SingleLanguageDependencyAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/TreeElementAsNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/trace.info create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/ApplicationPlugin_AppPluginPart.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/MPSNodeReferenceSerializer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/Mpsadapters_ApplicationPlugin.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/trace.info create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/Binding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudDataDependency.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudIcons.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudNodeTreeNodeCreationMethods.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudRepository.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModel.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModule.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModules.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CommandHelper.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ELockType.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ForeignNodeReference.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ICloudRepository.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/INodeUtils.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/IUserObjectContainer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/IterableOfINodeUtils.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/LetterInSquareIcon.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MPSNodeMapping.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MPSProjectUtils.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MessageHandler.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MetaModelSynchronizer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelAccess.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelBinding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelCloudExporter.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelCloudImportUtils.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelPersistenceWithFixedId.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelPropertiesSynchronizer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerConnection.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerConnections.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerNavigation.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelSynchronizer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelixNotifications.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelsSynchronizer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleBinding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleCheckout.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleUtils.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MpsReplicatedRepository.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/NodeMap.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/NonIndirectBranch.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/PNodeAdapterCreationMethods.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/PhysicalToCloudModelMapping.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectBinding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectModuleBinding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectModulesSynchronizer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/RootBinding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SModelUtils.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SModuleUtils.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SharedExecutors.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncDirection.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncQueue.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncTask.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/Synchronizer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TestCloudRepository.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransactionUtil.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransientModelsSynchronizer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransientModuleBinding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TreeChangeMulticaster.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TreeChangesCollector.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/UserObjectKey.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/WriteAccessUtil.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/_Adapters.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudBindingTreeNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudBranchTreeNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNodeBinding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNodeClassification.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudRootTreeNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudView.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/HistoryView.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/LoadingIcon.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/ModelServerTreeNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/RepositoryTreeNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeModelUtil.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeAccess.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeBinding.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeClassification.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/_Adapters.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/trace.info create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddBranch_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddChildNode_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModelNode_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModelServer_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModuleNode_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddProjectBinding_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddProjectNode_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddRepository_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddTransientModuleBinding_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ApplicationPlugin_AppPluginPart.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AutoBindings.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CheckoutAndSyncModule_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CheckoutModule_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalModulesCloudActions_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalModules_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalProjectsCloudActions_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalProjects_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudBindingGroup_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudBranchGroup_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudHistoryTool_Tool.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroupAddChild_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroupSetProperty_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroup_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudResourcesConfigurationComponent.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudRootGroup_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudTool_Tool.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyAndSyncPhysicalModuleOnCloud_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyAndSyncPhysicalProjectOnCloud_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyPhysicalModuleOnCloud_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/DeleteModule_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/DeleteProject_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/EModelixExecutionMode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/GetCloudRepositorySize_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/IconContainer.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/LoadHistoryForBranch_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/LoadHistoryForRepository_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/MetaMetaModelMappings.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelImportExport.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelServerGroup_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixConfigurationSystemProperties.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixExportConfiguration.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixImportConfiguration.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModuleAlreadyOnCloud_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Mpsplugin_ApplicationPlugin.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Mpsplugin_ProjectPlugin.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/NavigateToMpsNode_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/PersistedBindingConfiguration.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectMakeRunner.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectManagerExtensions.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectPlugin_ProjectPluginPart.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Reconnect_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveModelServer_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveRepository_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveTransientModuleBinding_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RepositoryGroup_ActionGroup.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/SetProperty_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowAuthenticationInfo_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowProperties_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowReferences_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/StoreAllModules_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/SwitchBranch_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/TextIcon_1.png create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/TextIcon_13262.png create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Unbind_Action.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/_Adapters.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/trace.info create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/CloudModuleTreeNode.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/CloudProjectViewExtension.java create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/trace.info create mode 100644 mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/trace.info diff --git a/mps-legacy-sync-plugin/src/main/java/de/slisson/mps/reflection/runtime/ReflectionUtil.java b/mps-legacy-sync-plugin/src/main/java/de/slisson/mps/reflection/runtime/ReflectionUtil.java new file mode 100644 index 00000000..83b1f404 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/de/slisson/mps/reflection/runtime/ReflectionUtil.java @@ -0,0 +1,59 @@ +package de.slisson.mps.reflection.runtime; + +/*Generated by MPS */ + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.Method; + +public class ReflectionUtil { + public static Object readField(Class cls, Object obj, String fieldName) { + try { + Field field = cls.getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(obj); + } catch (Exception ex) { + throw new RuntimeException("Cannot read field '" + fieldName + "' in class '" + cls + "' of object: " + obj, ex); + } + } + public static void writeField(Class cls, Object obj, String fieldName, Object value) { + try { + Field field = cls.getDeclaredField(fieldName); + field.setAccessible(true); + if (Modifier.isFinal(field.getModifiers())) { + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + int originalModifier = field.getModifiers(); + modifiersField.setInt(field, originalModifier & ~(Modifier.FINAL)); + } + field.set(obj, value); + } catch (Exception ex) { + throw new RuntimeException("Cannot write field '" + fieldName + "' in class '" + cls + "' of object: " + obj, ex); + } + } + public static Object callMethod(Class cls, Object obj, String methodName, Class[] argumentTypes, Object[] arguments) { + try { + Method method = cls.getDeclaredMethod(methodName, argumentTypes); + method.setAccessible(true); + return method.invoke(obj, arguments); + } catch (Exception ex) { + throw new RuntimeException("Cannot call method '" + methodName + "' in class '" + cls + "' of object: " + obj, ex); + } + } + public static void callVoidMethod(Class cls, Object obj, String methodName, Class[] argumentTypes, Object[] arguments) { + callMethod(cls, obj, methodName, argumentTypes, arguments); + } + public static Object callStaticMethod(Class cls, String methodName, Class[] argumentTypes, Object[] arguments) { + return callMethod(cls, null, methodName, argumentTypes, arguments); + } + public static void callStaticVoidMethod(Class cls, String methodName, Class[] argumentTypes, Object[] arguments) { + callStaticMethod(cls, methodName, argumentTypes, arguments); + } + public static Class getClass(String fqName) { + try { + return Class.forName(fqName); + } catch (ClassNotFoundException ex) { + throw new RuntimeException("", ex); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/common/AuthorOverride.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/common/AuthorOverride.java new file mode 100644 index 00000000..f13143e6 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/common/AuthorOverride.java @@ -0,0 +1,25 @@ +package org.modelix.common; + +/*Generated by MPS */ + +import de.q60.mps.incremental.util.ContextValue; + +public class AuthorOverride { + public static ContextValue AUTHOR = new ContextValue(); + private static String instanceOwner = null; + + public static void setInstanceOwner(String owner) { + instanceOwner = owner; + } + + public static String apply(String author) { + String override = AUTHOR.getValue(); + if ((override != null && override.length() > 0)) { + return override; + } + if ((author == null || author.length() == 0) && (instanceOwner != null && instanceOwner.length() > 0)) { + return instanceOwner; + } + return author; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/common/InstanceJwtToken.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/common/InstanceJwtToken.java new file mode 100644 index 00000000..0f32597d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/common/InstanceJwtToken.java @@ -0,0 +1,8 @@ +package org.modelix.common; + +/*Generated by MPS */ + + +public class InstanceJwtToken { + public static String token = System.getenv("INITIAL_JWT_TOKEN"); +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/common/PropertyOrEnv.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/common/PropertyOrEnv.java new file mode 100644 index 00000000..9273b7c1 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/common/PropertyOrEnv.java @@ -0,0 +1,31 @@ +package org.modelix.common; + +/*Generated by MPS */ + + +public class PropertyOrEnv { + public static String get(String name) { + String value = System.getProperty(name); + if ((value == null || value.length() == 0)) { + value = System.getenv(name); + } + if ((value == null || value.length() == 0) && name.contains(".")) { + String withoutDots = name.replace('.', '_'); + value = System.getProperty(withoutDots); + if ((value == null || value.length() == 0)) { + value = System.getenv(withoutDots); + } + } + return value; + } + + public static String getOrElse(String name, String defaultValue) { + String value = get(name); + return ((value != null && value.length() > 0) ? value : defaultValue); + } + + public static boolean getOrElseBoolean(String name, boolean defaultValue) { + String value = get(name); + return ((value != null && value.length() > 0) ? Boolean.parseBoolean(value) : defaultValue); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/common/trace.info b/mps-legacy-sync-plugin/src/main/java/org/modelix/common/trace.info new file mode 100644 index 00000000..5de183eb --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/common/trace.info @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ANode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ANode.java new file mode 100644 index 00000000..d7a0ac0b --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ANode.java @@ -0,0 +1,368 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import jetbrains.mps.smodel.SNode; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Objects; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.model.SNodeId; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.model.SNodeReference; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import jetbrains.mps.smodel.SReference; +import org.jetbrains.mps.openapi.language.SProperty; +import java.util.Collection; +import jetbrains.mps.util.IterableUtil; + +public class ANode extends SNode implements org.jetbrains.mps.openapi.model.SNode { + private static String USER_OBJECT_KEY = ANode.class.getName(); + + public static SNode wrap(org.jetbrains.mps.openapi.model.SNode nodeToWrap) { + if (nodeToWrap == null) { + return null; + } + if (nodeToWrap instanceof SNode) { + // The purpose of ANode is to allow casts to jetbrains.mps.smodel.SNode. + // No ANode required if it already is a subclass of jetbrains.mps.smodel.SNode. + return ((SNode) nodeToWrap); + } + ANode instance = as_ile5t_a0a2a2(nodeToWrap.getUserObject(USER_OBJECT_KEY), ANode.class); + if (instance == null) { + instance = new ANode(nodeToWrap); + nodeToWrap.putUserObject(USER_OBJECT_KEY, instance); + } + return instance; + } + + public static org.jetbrains.mps.openapi.model.SNode unwrap(org.jetbrains.mps.openapi.model.SNode nodeToUnwrap) { + if (nodeToUnwrap == null) { + return null; + } + if (nodeToUnwrap instanceof ANode) { + return ((ANode) nodeToUnwrap).node; + } + return nodeToUnwrap; + } + + private org.jetbrains.mps.openapi.model.SNode node; + + public ANode(org.jetbrains.mps.openapi.model.SNode node) { + super(new DummyConcept(), new DummySNodeId()); + this.node = node; + + // We don't really want to extend SNode, but some code in the editor is coupled to this class. + // Here all fields of this class are set to null, because we override all methods. + for (Field field : SNode.class.getDeclaredFields()) { + field.setAccessible(true); + if (Modifier.isStatic(field.getModifiers())) { + continue; + } + if (Modifier.isFinal(field.getModifiers())) { + continue; + } + if (Objects.equals(field.getName(), "myOwner")) { + continue; + } + try { + field.set(this, null); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + } + + @Nullable + @Override + public SModel getModel() { + return node.getModel(); + } + @Override + public SNodeId getNodeId() { + return node.getNodeId(); + } + @NotNull + @Override + public SNodeReference getReference() { + return new ANodeReference(node.getReference()); + } + @NotNull + @Override + public SConcept getConcept() { + return node.getConcept(); + } + @Override + public boolean isInstanceOfConcept(@NotNull SAbstractConcept concept) { + return node.isInstanceOfConcept(concept); + } + @Override + public String getPresentation() { + return node.getPresentation(); + } + @Nullable + @Override + public String getName() { + return node.getName(); + } + @Override + public void addChild(@NotNull SContainmentLink link, @NotNull org.jetbrains.mps.openapi.model.SNode node) { + throw new UnsupportedOperationException(); + } + @Override + public void insertChildBefore(@NotNull SContainmentLink link, @NotNull org.jetbrains.mps.openapi.model.SNode node, @Nullable org.jetbrains.mps.openapi.model.SNode node1) { + throw new UnsupportedOperationException(); + } + @Override + public void insertChildAfter(@NotNull SContainmentLink link, @NotNull org.jetbrains.mps.openapi.model.SNode node, @Nullable org.jetbrains.mps.openapi.model.SNode node1) { + throw new UnsupportedOperationException(); + } + @Override + public void removeChild(@NotNull org.jetbrains.mps.openapi.model.SNode node) { + throw new UnsupportedOperationException(); + } + @Override + public void delete() { + node.delete(); + } + @NotNull + @Override + public SNode getContainingRoot() { + return wrap(node.getContainingRoot()); + } + @Nullable + @Override + public SContainmentLink getContainmentLink() { + return node.getContainmentLink(); + } + @Nullable + @Override + public org.jetbrains.mps.openapi.model.SNode getFirstChild() { + return wrap(node.getFirstChild()); + } + @Nullable + @Override + public org.jetbrains.mps.openapi.model.SNode getLastChild() { + return wrap(node.getLastChild()); + } + @Nullable + @Override + public SNode getPrevSibling() { + return wrap(node.getPrevSibling()); + } + @Nullable + @Override + public SNode getNextSibling() { + return wrap(node.getNextSibling()); + } + @NotNull + @Override + public List getChildren(SContainmentLink link) { + Iterable children = node.getChildren(link); + return Sequence.fromIterable(children).select(new ISelector() { + public SNode select(org.jetbrains.mps.openapi.model.SNode it) { + return wrap(it); + } + }).toListSequence(); + } + @NotNull + @Override + public List getChildren() { + Iterable children = node.getChildren(); + return Sequence.fromIterable(children).select(new ISelector() { + public SNode select(org.jetbrains.mps.openapi.model.SNode it) { + return wrap(it); + } + }).toListSequence(); + } + @Override + public void setReferenceTarget(@NotNull SReferenceLink link, @Nullable org.jetbrains.mps.openapi.model.SNode target) { + this.node.setReferenceTarget(link, unwrap(target)); + } + @Nullable + @Override + public SNode getReferenceTarget(@NotNull SReferenceLink link) { + return wrap(node.getReferenceTarget(link)); + } + @Nullable + @Override + public SReference getReference(@NotNull SReferenceLink link) { + return AReference.wrap(node.getReference(link)); + } + @Override + public void setReference(@NotNull SReferenceLink link, @Nullable org.jetbrains.mps.openapi.model.SReference reference) { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public List getReferences() { + Iterable references = node.getReferences(); + return Sequence.fromIterable(references).select(new ISelector() { + public SReference select(org.jetbrains.mps.openapi.model.SReference it) { + SReference r = new AReference(it); + return r; + } + }).toListSequence(); + } + @NotNull + @Override + public Iterable getProperties() { + return node.getProperties(); + } + @Override + public boolean hasProperty(@NotNull SProperty property) { + return node.hasProperty(property); + } + @Nullable + @Override + public String getProperty(@NotNull SProperty property) { + return node.getProperty(property); + } + @Override + public void setProperty(@NotNull SProperty property, @Nullable String value) { + node.setProperty(property, value); + } + @Override + public Object getUserObject(Object key) { + return node.getUserObject(key); + } + @Override + public void putUserObject(Object key, @Nullable Object value) { + node.putUserObject(key, value); + } + @Override + public Iterable getUserObjectKeys() { + return node.getUserObjectKeys(); + } + @Deprecated + @Override + public String getRoleInParent() { + return node.getRoleInParent(); + } + + @Deprecated + @Override + public void setProperty(String string, String string1) { + throw new UnsupportedOperationException(); + } + @Deprecated + @Override + public Collection getPropertyNames() { + return IterableUtil.asList(node.getPropertyNames()); + } + @Deprecated + @Override + public void setReferenceTarget(String string, @Nullable org.jetbrains.mps.openapi.model.SNode node) { + throw new UnsupportedOperationException(); + } + @Deprecated + @Override + public SNode getReferenceTarget(String string) { + return wrap(node.getReferenceTarget(string)); + } + @Deprecated + @Override + public SReference getReference(String role) { + throw new UnsupportedOperationException(); + } + @Deprecated + @Override + public void setReference(String string, @Nullable org.jetbrains.mps.openapi.model.SReference reference) { + throw new UnsupportedOperationException(); + } + @Deprecated + @Override + public void insertChildBefore(String role, org.jetbrains.mps.openapi.model.SNode newChild, @Nullable org.jetbrains.mps.openapi.model.SNode anchor) { + node.insertChildBefore(role, newChild, unwrap(anchor)); + } + @Deprecated + @Override + public void addChild(String role, org.jetbrains.mps.openapi.model.SNode newChild) { + node.addChild(role, newChild); + } + @Deprecated + @Override + @NotNull + public List getChildren(String role) { + Iterable children = node.getChildren(role); + return Sequence.fromIterable(children).select(new ISelector() { + public SNode select(org.jetbrains.mps.openapi.model.SNode it) { + return (SNode) (Object) it; + } + }).toListSequence(); + } + + + + + + + @Override + public String toString() { + return "ANode"; + } + @Override + public void setId(@Nullable SNodeId id) { + throw new UnsupportedOperationException(); + } + @Override + protected SNode firstChild() { + throw new UnsupportedOperationException(); + } + @Override + protected SNode treePrevious() { + throw new UnsupportedOperationException(); + } + @Override + public SNode treeNext() { + throw new UnsupportedOperationException(); + } + @Override + protected SNode treeParent() { + return wrap(node.getParent()); + } + @Override + protected void children_insertBefore(SNode anchor, @NotNull SNode node) { + throw new UnsupportedOperationException(); + } + @Override + protected void children_remove(@NotNull SNode node) { + throw new UnsupportedOperationException(); + } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o instanceof NodeToSNodeAdapter) { + throw new RuntimeException("Forgot to wrap an SNode with an ANode?"); + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + ANode that = (ANode) o; + if ((node != null ? !(node.equals(that.node)) : that.node != null)) { + return false; + } + + return true; + } + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((node != null ? ((Object) node).hashCode() : 0)); + return result; + } + private static T as_ile5t_a0a2a2(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ANodeReference.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ANodeReference.java new file mode 100644 index 00000000..0906f16e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ANodeReference.java @@ -0,0 +1,41 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SNodeReference; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.mps.openapi.model.SNodeId; +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.mps.openapi.module.SRepository; + +public class ANodeReference implements SNodeReference { + + private SNodeReference ref; + + public ANodeReference(SNodeReference ref1) { + ref = ref1; + } + + @Nullable + @Override + public SModelReference getModelReference() { + return ref.getModelReference(); + } + + @Nullable + @Override + public SNodeId getNodeId() { + return ref.getNodeId(); + } + + @Nullable + @Override + public SNode resolve(SRepository repository) { + return ANode.wrap(ref.resolve(repository)); + } + + public SNodeReference unwrap() { + return ref; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/AReference.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/AReference.java new file mode 100644 index 00000000..45450136 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/AReference.java @@ -0,0 +1,78 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import jetbrains.mps.smodel.SReference; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.mps.openapi.model.SNodeReference; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.mps.openapi.model.SNodeId; + +public class AReference extends SReference { + + public static SReference wrap(org.jetbrains.mps.openapi.model.SReference refToWrap) { + if (refToWrap == null) { + return null; + } + if (refToWrap instanceof SReference) { + return ((SReference) refToWrap); + } + return new AReference(refToWrap); + } + + private org.jetbrains.mps.openapi.model.SReference reference; + + public AReference(org.jetbrains.mps.openapi.model.SReference reference) { + super(reference.getLink(), null); + this.reference = reference; + } + @Deprecated + @Override + public String getRole() { + throw new UnsupportedOperationException(); + } + @Override + public SReferenceLink getLink() { + return reference.getLink(); + } + @Override + public SNode getSourceNode() { + return ANode.wrap(reference.getSourceNode()); + } + @Override + public SNodeReference getTargetNodeReference() { + return new ANodeReference(reference.getTargetNodeReference()); + } + @Nullable + @Override + public SModelReference getTargetSModelReference() { + return reference.getTargetSModelReference(); + } + @Nullable + @Override + public SNodeId getTargetNodeId() { + return reference.getTargetNodeId(); + } + @Override + public void makeDirect() { + throw new UnsupportedOperationException(); + } + @Override + public boolean makeIndirect() { + throw new UnsupportedOperationException(); + } + @Override + public String getResolveInfo() { + return null; + } + @Override + public void setResolveInfo(String info) { + throw new UnsupportedOperationException(); + } + @Override + protected SNode getTargetNode_internal(SReference.ProblemReporter report) { + return ANode.wrap(reference.getTargetNode()); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/BootstrapConceptMappings.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/BootstrapConceptMappings.java new file mode 100644 index 00000000..4a3518dc --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/BootstrapConceptMappings.java @@ -0,0 +1,110 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import java.util.Map; +import jetbrains.mps.smodel.adapter.ids.SConceptId; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import org.modelix.model.api.IConcept; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import jetbrains.mps.smodel.adapter.ids.MetaIdHelper; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import java.util.Objects; +import jetbrains.mps.smodel.runtime.ConceptDescriptor; +import jetbrains.mps.smodel.language.ConceptRegistry; +import jetbrains.mps.smodel.runtime.illegal.IllegalConceptDescriptor; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class BootstrapConceptMappings { + public static final BootstrapConceptMappings INSTANCE = new BootstrapConceptMappings(); + + private Map sconcept2uid = MapSequence.fromMap(new HashMap()); + private Map uid2sconcept = MapSequence.fromMap(new HashMap()); + private Map concepts = MapSequence.fromMap(new HashMap()); + + public void register(IConcept concept, SAbstractConcept sconcept) { + register(concept, MetaIdHelper.getConcept(sconcept)); + } + + public void unregister(IConcept concept, SAbstractConcept sconcept) { + unregister(concept, MetaIdHelper.getConcept(sconcept)); + } + + public synchronized void register(final IConcept concept, final SConceptId sconceptId) { + final String uid = concept.getUID(); + uid2sconcept = modifyCopy(uid2sconcept, new _FunctionTypes._void_P1_E0>() { + public void invoke(Map copy) { + MapSequence.fromMap(copy).put(uid, sconceptId); + } + }); + sconcept2uid = modifyCopy(sconcept2uid, new _FunctionTypes._void_P1_E0>() { + public void invoke(Map copy) { + MapSequence.fromMap(copy).put(sconceptId, uid); + } + }); + concepts = modifyCopy(concepts, new _FunctionTypes._void_P1_E0>() { + public void invoke(Map copy) { + MapSequence.fromMap(copy).put(uid, concept); + } + }); + } + + public synchronized void unregister(IConcept concept, final SConceptId sconceptId) { + final String uid = concept.getUID(); + if (!(Objects.equals(getSConceptId(uid), sconceptId))) { + throw new RuntimeException("Attempt to unregister " + uid + " = " + sconceptId + " while " + getSConceptId(uid) + " was registered"); + } + uid2sconcept = modifyCopy(uid2sconcept, new _FunctionTypes._void_P1_E0>() { + public void invoke(Map copy) { + MapSequence.fromMap(copy).removeKey(uid); + } + }); + sconcept2uid = modifyCopy(sconcept2uid, new _FunctionTypes._void_P1_E0>() { + public void invoke(Map copy) { + MapSequence.fromMap(copy).removeKey(sconceptId); + } + }); + concepts = modifyCopy(concepts, new _FunctionTypes._void_P1_E0>() { + public void invoke(Map copy) { + MapSequence.fromMap(copy).removeKey(uid); + } + }); + } + + public SAbstractConcept getSConcept(IConcept concept) { + SConceptId sconceptId = getSConceptId(concept.getUID()); + if (sconceptId == null) { + return null; + } + ConceptDescriptor conceptDescriptor = ConceptRegistry.getInstance().getConceptDescriptor(sconceptId); + if (conceptDescriptor instanceof IllegalConceptDescriptor) { + return null; + } + return MetaAdapterFactory.getAbstractConcept(conceptDescriptor); + } + + public IConcept getConcept(SAbstractConcept concept) { + SConceptId sconceptId = MetaIdHelper.getConcept(concept); + String uid = getUID(sconceptId); + if (uid == null) { + return null; + } + return MapSequence.fromMap(concepts).get(uid); + } + + public SConceptId getSConceptId(String uid) { + return MapSequence.fromMap(uid2sconcept).get(uid); + } + + public String getUID(SConceptId sconceptId) { + return MapSequence.fromMap(sconcept2uid).get(sconceptId); + } + + private Map modifyCopy(Map map, _FunctionTypes._void_P1_E0> modifier) { + Map copy = MapSequence.fromMap(new HashMap()); + MapSequence.fromMap(copy).putAll(map); + modifier.invoke(copy); + return copy; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DevKitDependencyAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DevKitDependencyAsNode.java new file mode 100644 index 00000000..a137c62b --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DevKitDependencyAsNode.java @@ -0,0 +1,321 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.module.SModuleReference; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.area.IArea; +import org.modelix.model.api.INodeReference; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConcept; +import jetbrains.mps.internal.collections.runtime.LinkedListSequence; +import java.util.LinkedList; +import java.util.Collections; +import org.modelix.model.api.IChildLink; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import org.modelix.model.api.IConceptReference; +import java.util.Objects; +import java.util.List; +import org.modelix.model.api.IProperty; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.modelix.model.api.IReferenceLink; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.mps.openapi.module.SModuleId; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; + +public class DevKitDependencyAsNode implements INode { + private SModuleReference moduleReference; + private SModule moduleImporter; + private SModel modelImporter; + + public DevKitDependencyAsNode(SModuleReference moduleReference, SModule importer) { + this.moduleReference = moduleReference; + this.moduleImporter = importer; + } + + public DevKitDependencyAsNode(SModuleReference moduleReference, SModel importer) { + this.moduleReference = moduleReference; + this.modelImporter = importer; + } + + @NotNull + @Override + public IArea getArea() { + return new MPSArea(); + } + + @Override + public boolean isValid() { + return true; + } + + @NotNull + @Override + public INodeReference getReference() { + if (this.moduleImporter != null) { + return new NodeReference(this.moduleImporter.getModuleReference(), this.moduleReference.getModuleId()); + } + if (this.modelImporter != null) { + return new NodeReference(this.modelImporter.getReference(), this.moduleReference.getModuleId()); + } + throw new IllegalStateException(); + } + + @Nullable + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.DevkitDependency$Ns); + } + + @Nullable + @Override + public String getRoleInParent() { + if (this.moduleImporter != null) { + return LINKS.languageDependencies$vKlY.getName(); + } + if (this.modelImporter != null) { + return LINKS.usedLanguages$QK4E.getName(); + } + throw new IllegalStateException(); + } + + @Nullable + @Override + public INode getParent() { + if (this.moduleImporter != null) { + SModuleAsNode.wrap(this.moduleImporter); + } + if (this.modelImporter != null) { + SModelAsNode.wrap(this.modelImporter); + } + throw new IllegalStateException(); + } + + @NotNull + @Override + public Iterable getChildren(@Nullable String role) { + return LinkedListSequence.fromLinkedListNew(new LinkedList()); + } + + @NotNull + @Override + public Iterable getAllChildren() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + Iterable links = concept.getAllChildLinks(); + return Sequence.fromIterable(links).select(new ISelector>() { + public Iterable select(IChildLink it) { + return getChildren(it.getName()); + } + }).translate(new ITranslator2, INode>() { + public Iterable translate(Iterable it) { + return it; + } + }); + } + + @Override + public void moveChild(@Nullable String string, int i, @NotNull INode node) { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public INode addNewChild(@Nullable String string, int i, @Nullable IConcept concept) { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public INode addNewChild(@Nullable String string, int i, @Nullable IConceptReference reference) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeChild(@NotNull INode node) { + throw new UnsupportedOperationException(); + } + + @Nullable + @Override + public INode getReferenceTarget(@NotNull String role) { + return null; + } + @Nullable + @Override + public INodeReference getReferenceTargetRef(@NotNull String string) { + return null; + } + + @Override + public void setReferenceTarget(@NotNull String string, @Nullable INode node) { + throw new UnsupportedOperationException(); + } + @Override + public void setReferenceTarget(@NotNull String string, @Nullable INodeReference reference) { + throw new UnsupportedOperationException(); + } + + @Nullable + @Override + public String getPropertyValue(@NotNull String propertyName) { + if (Objects.equals(PROPS.name$lpYq.getName(), propertyName)) { + return this.moduleReference.getModuleName(); + } else if (Objects.equals(PROPS.uuid$lpJp.getName(), propertyName)) { + return this.moduleReference.getModuleId().toString(); + } else { + return null; + } + } + @Override + public void setPropertyValue(@NotNull String string, @Nullable String string1) { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public List getPropertyRoles() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + List allProperties = concept.getAllProperties(); + return ListSequence.fromList(allProperties).select(new ISelector() { + public String select(IProperty it) { + return it.getName(); + } + }).toListSequence(); + } + + @NotNull + @Override + public List getReferenceRoles() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + List allReferenceLinks = concept.getAllReferenceLinks(); + return ListSequence.fromList(allReferenceLinks).select(new ISelector() { + public String select(IReferenceLink it) { + return it.getName(); + } + }).toListSequence(); + } + + public static class NodeReference implements INodeReference { + private SModuleReference userModuleReference; + private SModelReference userModel; + private SModuleId usedModuleId; + + public NodeReference(SModuleReference userModuleReference, SModuleId usedModuleId) { + this.userModuleReference = userModuleReference; + this.usedModuleId = usedModuleId; + } + + public NodeReference(SModelReference userModel, SModuleId usedModuleId) { + this.userModel = userModel; + this.usedModuleId = usedModuleId; + } + + @Nullable + @Override + public INode resolveNode(@Nullable IArea area) { + SRepository repo = null; + if (area != null) { + List areas = area.collectAreas(); + repo = ListSequence.fromList(areas).ofType(MPSArea.class).select(new ISelector() { + public SRepository select(MPSArea it) { + return it.getRepository(); + } + }).where(new NotNullWhereFilter()).first(); + } + if (repo == null) { + repo = MPSModuleRepository.getInstance(); + } + + if (this.userModuleReference != null) { + SModule user = userModuleReference.resolve(repo); + if (user == null) { + return null; + } + + return new SModuleAsNode(user).findDevKitDependency(this.usedModuleId); + } else if (this.userModel != null) { + SModel model = userModel.resolve(repo); + return new SModelAsNode(model).findDevKitDependency(this.usedModuleId); + } else { + throw new IllegalStateException(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if (Objects.equals(this.userModuleReference, that.userModuleReference)) { + return false; + } + if (Objects.equals(this.userModel, that.userModel)) { + return false; + } + if (Objects.equals(this.usedModuleId, that.usedModuleId)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((userModuleReference != null ? ((Object) userModuleReference).hashCode() : 0)); + result = 11 * result + ((usedModuleId != null ? ((Object) usedModuleId).hashCode() : 0)); + result = 37 * result + ((userModel != null ? ((Object) userModel).hashCode() : 0)); + return result; + } + } + + @Nullable + @Override + public IConceptReference getConceptReference() { + return check_d9amqo_a0a64(getConcept(), this); + } + private static IConceptReference check_d9amqo_a0a64(IConcept checkedDotOperand, DevKitDependencyAsNode checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getReference(); + } + return null; + } + + private static final class CONCEPTS { + /*package*/ static final SConcept DevkitDependency$Ns = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x7c527144386aca16L, "org.modelix.model.repositoryconcepts.structure.DevkitDependency"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink languageDependencies$vKlY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299187L, "languageDependencies"); + /*package*/ static final SContainmentLink usedLanguages$QK4E = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x4aaf28cf2092e98eL, "usedLanguages"); + } + + private static final class PROPS { + /*package*/ static final SProperty uuid$lpJp = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x7c527144386aca0fL, 0x7c527144386aca12L, "uuid"); + /*package*/ static final SProperty name$lpYq = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x7c527144386aca0fL, 0x7c527144386aca13L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DummyConcept.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DummyConcept.java new file mode 100644 index 00000000..ec17e6bc --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DummyConcept.java @@ -0,0 +1,98 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.language.SInterfaceConcept; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.language.SLanguage; +import java.util.Collection; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.mps.openapi.model.SNodeReference; + +public class DummyConcept implements SConcept { + + @Nullable + @Override + public SConcept getSuperConcept() { + throw new UnsupportedOperationException(); + } + @Override + public Iterable getSuperInterfaces() { + throw new UnsupportedOperationException(); + } + @Override + public boolean isRootable() { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public String getName() { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public SLanguage getLanguage() { + throw new UnsupportedOperationException(); + } + @Override + public Collection getReferenceLinks() { + throw new UnsupportedOperationException(); + } + @Override + public Collection getContainmentLinks() { + throw new UnsupportedOperationException(); + } + @Override + public Collection getProperties() { + throw new UnsupportedOperationException(); + } + @Override + public boolean isSubConceptOf(SAbstractConcept concept) { + throw new UnsupportedOperationException(); + } + @Override + public boolean isAbstract() { + throw new UnsupportedOperationException(); + } + @Deprecated + @Nullable + @Override + public SNode getDeclarationNode() { + throw new UnsupportedOperationException(); + } + @Nullable + @Override + public SNodeReference getSourceNode() { + throw new UnsupportedOperationException(); + } + @Override + public boolean isValid() { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public String getConceptAlias() { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public String getShortDescription() { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public String getHelpUrl() { + throw new UnsupportedOperationException(); + } + @Deprecated + @Override + public String getQualifiedName() { + throw new UnsupportedOperationException(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DummySNodeId.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DummySNodeId.java new file mode 100644 index 00000000..575c5b16 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/DummySNodeId.java @@ -0,0 +1,12 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SNodeId; + +public class DummySNodeId implements SNodeId { + @Override + public String getType() { + throw new UnsupportedOperationException(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/EModelMode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/EModelMode.java new file mode 100644 index 00000000..a577040d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/EModelMode.java @@ -0,0 +1,9 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + + +public enum EModelMode { + ADAPTER(), + NULL() +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/JavaModuleFacetAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/JavaModuleFacetAsNode.java new file mode 100644 index 00000000..78e1edfa --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/JavaModuleFacetAsNode.java @@ -0,0 +1,187 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import jetbrains.mps.project.facets.JavaModuleFacet; +import jetbrains.mps.project.AbstractModule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConcept; +import java.util.Objects; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.module.SModule; +import org.modelix.model.api.INodeReference; +import org.jetbrains.mps.openapi.module.SModuleReference; +import org.modelix.model.area.IArea; +import org.jetbrains.mps.openapi.module.SModuleFacet; +import jetbrains.mps.vfs.IFile; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SContainmentLink; + +public class JavaModuleFacetAsNode extends TreeElementAsNode { + + private TreeElementAsNode.IPropertyAccessor generatedAccessor = new ReadOnlyPropertyAccessor() { + @Override + public String get(JavaModuleFacet element) { + // Based on this, I would expect the value to be always true, if not for some legacy code https://github.com/JetBrains/MPS/blob/2820965ff7b8836ed1d14adaf1bde29744c88147/core/project/source/jetbrains/mps/project/facets/JavaModuleFacetImpl.java + return Boolean.toString(true); + } + }; + + private TreeElementAsNode.IPropertyAccessor pathAccessor = new ReadOnlyPropertyAccessor() { + @Override + public String get(JavaModuleFacet element) { + if (element == null) { + throw new IllegalStateException("The JavaModuleFacet should not be null"); + } + String originalPath = check_r9f4ri_a0b0a0a0d(element.getClassesGen()); + String moduleRoot = null; + if (element.getModule() instanceof AbstractModule) { + AbstractModule module = ((AbstractModule) element.getModule()); + moduleRoot = check_r9f4ri_a0b0d0a0a0d(check_r9f4ri_a0a1a3a0a0a3(check_r9f4ri_a0a0b0d0a0a0d(module))); + } + String path = originalPath; + if (moduleRoot != null && check_r9f4ri_a0f0a0a0d(originalPath, moduleRoot)) { + path = "${module}" + originalPath.substring(moduleRoot.length()); + } + return path; + } + + }; + + public JavaModuleFacetAsNode(@NotNull JavaModuleFacet facet) { + super(facet); + } + + @Nullable + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.JavaModuleFacet$5E); + } + + @Override + protected TreeElementAsNode.IPropertyAccessor getPropertyAccessor(String role) { + if (Objects.equals(role, PROPS.generated$A44R.getName())) { + return generatedAccessor; + } + if (Objects.equals(role, PROPS.path$A4yT.getName())) { + return pathAccessor; + } + return super.getPropertyAccessor(role); + } + + @Nullable + @Override + public String getRoleInParent() { + return LINKS.facets$vw9T.getName(); + } + + @Nullable + @Override + public INode getParent() { + SModule module = this.getElement().getModule(); + return (module == null ? null : new SModuleAsNode(module)); + } + + @NotNull + @Override + public INodeReference getReference() { + SModule module = this.getElement().getModule(); + return new NodeReference(module.getModuleReference()); + } + + public static class NodeReference implements INodeReference { + private SModuleReference moduleReference; + + public NodeReference(SModuleReference moduleReference) { + this.moduleReference = moduleReference; + } + + @Nullable + @Override + public INode resolveNode(@Nullable IArea area) { + SModule module = check_r9f4ri_a0a0e71(((SModuleAsNode) new SModuleAsNode.NodeReference(moduleReference).resolveNode(area))); + if (module == null) { + return null; + } + SModuleFacet moduleFacet = module.getFacetOfType(JavaModuleFacet.FACET_TYPE); + return new JavaModuleFacetAsNode(((JavaModuleFacet) moduleFacet)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if (!(Objects.equals(this.moduleReference, that.moduleReference))) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((moduleReference != null ? moduleReference.hashCode() : 0)); + return result; + } + private static SModule check_r9f4ri_a0a0e71(SModuleAsNode checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getElement(); + } + return null; + } + } + + private static String check_r9f4ri_a0b0a0a0d(IFile checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getPath(); + } + return null; + } + private static String check_r9f4ri_a0b0d0a0a0d(IFile checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getPath(); + } + return null; + } + private static IFile check_r9f4ri_a0a1a3a0a0a3(IFile checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getParent(); + } + return null; + } + private static IFile check_r9f4ri_a0a0b0d0a0a0d(AbstractModule checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getDescriptorFile(); + } + return null; + } + private static boolean check_r9f4ri_a0f0a0a0d(String checkedDotOperand, String moduleRoot) { + if (null != checkedDotOperand) { + return checkedDotOperand.startsWith(moduleRoot); + } + return false; + } + + private static final class CONCEPTS { + /*package*/ static final SConcept JavaModuleFacet$5E = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde9535299166L, "org.modelix.model.repositoryconcepts.structure.JavaModuleFacet"); + } + + private static final class PROPS { + /*package*/ static final SProperty generated$A44R = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde9535299166L, 0x1e9fde9535299167L, "generated"); + /*package*/ static final SProperty path$A4yT = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde9535299166L, 0x1e9fde9535299169L, "path"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink facets$vw9T = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde953529916cL, "facets"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/MPSArea.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/MPSArea.java new file mode 100644 index 00000000..57157871 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/MPSArea.java @@ -0,0 +1,199 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.area.IArea; +import org.modelix.model.area.IAreaReference; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConcept; +import org.modelix.model.api.IConceptReference; +import org.modelix.model.api.ConceptReference; +import jetbrains.mps.smodel.adapter.ids.SConceptId; +import jetbrains.mps.smodel.runtime.ConceptDescriptor; +import jetbrains.mps.smodel.language.ConceptRegistry; +import jetbrains.mps.smodel.runtime.illegal.IllegalConceptDescriptor; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import java.util.Objects; +import kotlin.jvm.functions.Function0; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import org.jetbrains.mps.openapi.module.ModelAccess; +import jetbrains.mps.smodel.GlobalModelAccess; +import org.modelix.model.api.INode; +import org.modelix.model.area.IAreaListener; +import org.modelix.model.api.INodeReference; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.api.IBranch; +import java.util.List; +import java.util.Collections; + +public class MPSArea implements IArea, IAreaReference { + + private SRepository repository; + + public MPSArea() { + this(MPSModuleRepository.getInstance()); + } + + public MPSArea(SRepository repository) { + this.repository = repository; + } + + @Override + public long getLockOrderingPriority() { + return 100L << 32; + } + + @NotNull + @Override + public IAreaReference getReference() { + return this; + } + + @Nullable + @Override + public IConcept resolveConcept(@NotNull IConceptReference reference) { + if (!(reference instanceof ConceptReference)) { + return null; + } + String uid = ((ConceptReference) reference).getUid(); + if (uid.startsWith("mps:")) { + uid = uid.substring(4); + } + SConceptId conceptId; + try { + conceptId = SConceptId.deserialize(uid); + } catch (Exception ex) { + return null; + } + if (conceptId == null) { + return null; + } + ConceptDescriptor conceptDescriptor = ConceptRegistry.getInstance().getConceptDescriptor(conceptId); + if (conceptDescriptor instanceof IllegalConceptDescriptor) { + return null; + } + return SConceptAdapter.wrap(MetaAdapterFactory.getAbstractConcept(conceptDescriptor)); + } + + @Nullable + @Override + public IArea resolveArea(@NotNull IAreaReference reference) { + return (Objects.equals(reference, this) ? this : null); + } + + public SRepository getRepository() { + return repository; + } + + @Override + public boolean canRead() { + return getRepository().getModelAccess().canRead(); + } + + @Override + public boolean canWrite() { + return getRepository().getModelAccess().canWrite(); + } + + @Override + public T executeRead(@NotNull final Function0 f) { + final Wrappers._T result = new Wrappers._T(); + getRepository().getModelAccess().runReadAction(new Runnable() { + public void run() { + result.value = f.invoke(); + } + }); + return result.value; + } + + @Override + public T executeWrite(@NotNull final Function0 f) { + final Wrappers._T result = new Wrappers._T(); + ModelAccess modelAccess = getRepository().getModelAccess(); + if (modelAccess instanceof GlobalModelAccess) { + modelAccess.runWriteAction(new Runnable() { + public void run() { + result.value = f.invoke(); + } + }); + } else { + modelAccess.executeCommand(new Runnable() { + public void run() { + result.value = f.invoke(); + } + }); + } + return result.value; + } + + @NotNull + @Override + public INode getRoot() { + return new SRepositoryAsNode(getRepository()); + } + + @Override + public void addListener(@NotNull IAreaListener listener) { + throw new UnsupportedOperationException("Not implemented yet"); + } + + @Override + public void removeListener(@NotNull IAreaListener listener) { + throw new UnsupportedOperationException("Not implemented yet"); + } + + @Nullable + @Override + public INode resolveNode(@NotNull INodeReference reference) { + return resolveOriginalNode(reference); + } + + @Nullable + @Override + public INode resolveOriginalNode(@NotNull INodeReference reference) { + if (reference instanceof SNodeReferenceAdapter) { + SNode mpsNode = ((SNodeReferenceAdapter) reference).getReference().resolve(getRepository()); + return SNodeToNodeAdapter.wrap(mpsNode); + } + return null; + } + + @Nullable + @Override + public IBranch resolveBranch(@NotNull String id) { + return null; + } + + @NotNull + @Override + public List collectAreas() { + return Collections.singletonList(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + MPSArea that = (MPSArea) o; + if ((repository != null ? !(repository.equals(that.repository)) : that.repository != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((repository != null ? ((Object) repository).hashCode() : 0)); + return result; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/MPSLanguageRepository.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/MPSLanguageRepository.java new file mode 100644 index 00000000..eebadb75 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/MPSLanguageRepository.java @@ -0,0 +1,64 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.ILanguageRepository; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConcept; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.smodel.adapter.ids.SConceptId; +import jetbrains.mps.smodel.runtime.ConceptDescriptor; +import jetbrains.mps.smodel.language.ConceptRegistry; +import jetbrains.mps.smodel.runtime.illegal.IllegalConceptDescriptor; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.smodel.language.LanguageRegistry; +import java.util.function.Consumer; +import jetbrains.mps.smodel.language.LanguageRuntime; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; + +public class MPSLanguageRepository implements ILanguageRepository { + public static final MPSLanguageRepository INSTANCE = new MPSLanguageRepository(); + @Nullable + @Override + public IConcept resolveConcept(@NotNull String uid) { + if (!(uid.startsWith("mps:"))) { + return null; + } + SConceptId conceptId; + try { + conceptId = SConceptId.deserialize(uid.substring(4)); + } catch (Exception ex) { + return null; + } + if (conceptId == null) { + return null; + } + ConceptDescriptor conceptDescriptor = ConceptRegistry.getInstance().getConceptDescriptor(conceptId); + if (conceptDescriptor instanceof IllegalConceptDescriptor) { + return null; + } + return SConceptAdapter.wrap(MetaAdapterFactory.getAbstractConcept(conceptDescriptor)); + } + + @NotNull + @Override + public List getAllConcepts() { + final List result = ListSequence.fromList(new ArrayList()); + LanguageRegistry.getInstance().withAvailableLanguages(new Consumer() { + public void accept(LanguageRuntime language) { + Iterable concepts = language.getIdentity().getConcepts(); + ListSequence.fromList(result).addSequence(Sequence.fromIterable(concepts).select(new ISelector() { + public IConcept select(SAbstractConcept it) { + return SConceptAdapter.wrap(it); + } + })); + } + }); + return result; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ModelImportAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ModelImportAsNode.java new file mode 100644 index 00000000..085d14ef --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ModelImportAsNode.java @@ -0,0 +1,147 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SModel; +import org.modelix.model.api.INode; +import org.modelix.model.api.IConcept; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.api.INodeReference; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.area.IArea; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import org.jetbrains.mps.openapi.language.SContainmentLink; + +public class ModelImportAsNode extends TreeElementAsNode { + private static TreeElementAsNode.IReferenceAccessor modelAccessor = new TreeElementAsNode.IReferenceAccessor() { + public INode get(SModel model) { + return SModelAsNode.wrap(model); + } + @Override + public INode set(SModel element, INode target) { + throw new UnsupportedOperationException("Read only"); + } + }; + + private SModel importingModel; + + public ModelImportAsNode(SModel importedModel, SModel importingModel) { + super(importedModel); + this.importingModel = importingModel; + } + + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.ModelReference$sV); + } + + @Override + protected TreeElementAsNode.IChildAccessor getChildAccessor(String role) { + return super.getChildAccessor(role); + } + @Override + protected TreeElementAsNode.IPropertyAccessor getPropertyAccessor(String role) { + return super.getPropertyAccessor(role); + } + @Override + protected TreeElementAsNode.IReferenceAccessor getReferenceAccessor(String role) { + if (role.equals(LINKS.model$GJHn.getName())) { + return modelAccessor; + } + return super.getReferenceAccessor(role); + } + @Override + public INode getParent() { + return new SModelAsNode(importingModel); + } + @Override + public String getRoleInParent() { + return LINKS.modelImports$8DOI.getName(); + } + + @NotNull + @Override + public INodeReference getReference() { + return new NodeReference(getElement().getReference(), importingModel.getReference()); + } + + public static class NodeReference implements INodeReference { + private SModelReference importedModelRef; + private SModelReference importingModelRef; + + public NodeReference(SModelReference importedModelRef, SModelReference importingModelRef) { + this.importedModelRef = importedModelRef; + this.importingModelRef = importingModelRef; + } + + @Nullable + @Override + public INode resolveNode(@Nullable IArea area) { + SModel importedModel = check_c5rr7l_a0a0f61(new SModelAsNode.NodeReference(importedModelRef).resolveNode(area)); + if (importedModel == null) { + return null; + } + SModel importingModel = check_c5rr7l_a0c0f61(new SModelAsNode.NodeReference(importingModelRef).resolveNode(area)); + if (importingModel == null) { + return null; + } + return new ModelImportAsNode(importedModel, importingModel); + } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if ((importedModelRef != null ? !(importedModelRef.equals(that.importedModelRef)) : that.importedModelRef != null)) { + return false; + } + if ((importingModelRef != null ? !(importingModelRef.equals(that.importingModelRef)) : that.importingModelRef != null)) { + return false; + } + + return true; + } + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((importedModelRef != null ? ((Object) importedModelRef).hashCode() : 0)); + result = 31 * result + ((importingModelRef != null ? ((Object) importingModelRef).hashCode() : 0)); + return result; + } + public SModelReference getImportedModelRef() { + return this.importedModelRef; + } + public SModelReference getImportingModelRef() { + return this.importingModelRef; + } + private static SModel check_c5rr7l_a0a0f61(SModelAsNode checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getElement(); + } + return null; + } + private static SModel check_c5rr7l_a0c0f61(SModelAsNode checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getElement(); + } + return null; + } + } + + private static final class CONCEPTS { + /*package*/ static final SConcept ModelReference$sV = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x58dbe6e4d4f332a3L, "org.modelix.model.repositoryconcepts.structure.ModelReference"); + } + + private static final class LINKS { + /*package*/ static final SReferenceLink model$GJHn = MetaAdapterFactory.getReferenceLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x58dbe6e4d4f332a3L, 0x58dbe6e4d4f332a4L, "model"); + /*package*/ static final SContainmentLink modelImports$8DOI = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x58dbe6e4d4f32eb8L, "modelImports"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ModuleDependencyAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ModuleDependencyAsNode.java new file mode 100644 index 00000000..0ca677e4 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ModuleDependencyAsNode.java @@ -0,0 +1,278 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.module.SModuleReference; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.module.SDependencyScope; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConceptReference; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.area.IArea; +import org.modelix.model.api.INodeReference; +import org.modelix.model.api.IConcept; +import jetbrains.mps.internal.collections.runtime.LinkedListSequence; +import java.util.LinkedList; +import java.util.Collections; +import org.modelix.model.api.IChildLink; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import java.util.Objects; +import java.util.List; +import org.modelix.model.api.IProperty; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.modelix.model.api.IReferenceLink; +import org.jetbrains.mps.openapi.module.SModuleId; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; + +public class ModuleDependencyAsNode implements INode { + private SModuleReference moduleReference; + private int moduleVersion; + private SModule importer; + private boolean explicit; + private boolean reexport; + private SDependencyScope dependencyScope; + + public ModuleDependencyAsNode(SModuleReference moduleReference, int moduleVersion, boolean explicit, boolean reexport, SModule importer, SDependencyScope dependencyScope) { + this.moduleReference = moduleReference; + this.moduleVersion = moduleVersion; + this.explicit = explicit; + this.importer = importer; + this.reexport = reexport; + this.dependencyScope = dependencyScope; + } + + @Nullable + @Override + public IConceptReference getConceptReference() { + return getConcept().getReference(); + } + + @NotNull + @Override + public IArea getArea() { + return new MPSArea(); + } + @Override + public boolean isValid() { + return true; + } + @NotNull + @Override + public INodeReference getReference() { + return new NodeReference(this.importer.getModuleReference(), this.moduleReference.getModuleId()); + } + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.ModuleDependency$kc); + } + @Nullable + @Override + public String getRoleInParent() { + return LINKS.dependencies$vC8r.getName(); + } + @Nullable + @Override + public INode getParent() { + return SModuleAsNode.wrap(this.importer); + } + @NotNull + @Override + public Iterable getChildren(@Nullable String role) { + return LinkedListSequence.fromLinkedListNew(new LinkedList()); + } + @NotNull + @Override + public Iterable getAllChildren() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + Iterable links = concept.getAllChildLinks(); + return Sequence.fromIterable(links).select(new ISelector>() { + public Iterable select(IChildLink it) { + return getChildren(it.getName()); + } + }).translate(new ITranslator2, INode>() { + public Iterable translate(Iterable it) { + return it; + } + }); + } + @Override + public void moveChild(@Nullable String string, int i, @NotNull INode node) { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public INode addNewChild(@Nullable String string, int i, @Nullable IConcept concept) { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public INode addNewChild(@Nullable String string, int i, @Nullable IConceptReference reference) { + throw new UnsupportedOperationException(); + } + @Override + public void removeChild(@NotNull INode node) { + throw new UnsupportedOperationException(); + } + @Nullable + @Override + public INode getReferenceTarget(@NotNull String role) { + return null; + } + @Nullable + @Override + public INodeReference getReferenceTargetRef(@NotNull String string) { + return null; + } + @Override + public void setReferenceTarget(@NotNull String string, @Nullable INode node) { + throw new UnsupportedOperationException(); + } + @Override + public void setReferenceTarget(@NotNull String string, @Nullable INodeReference reference) { + throw new UnsupportedOperationException(); + } + @Nullable + @Override + public String getPropertyValue(@NotNull String propertyName) { + if (Objects.equals(PROPS.explicit$yR_K.getName(), propertyName)) { + return Boolean.toString(this.explicit); + } else if (Objects.equals(PROPS.name$Ahsh.getName(), propertyName)) { + return this.moduleReference.getModuleName(); + } else if (Objects.equals(PROPS.reexport$AblR.getName(), propertyName)) { + return Boolean.toString(this.reexport); + } else if (Objects.equals(PROPS.uuid$AbNT.getName(), propertyName)) { + return this.moduleReference.getModuleId().toString(); + } else if (Objects.equals(PROPS.version$yXGa.getName(), propertyName)) { + return Integer.toString(this.moduleVersion); + } else if (Objects.equals(PROPS.scope$mJmq.getName(), propertyName)) { + if (this.dependencyScope == null) { + return "UNSPECIFIED"; + } + return this.dependencyScope.toString(); + } else { + return null; + } + } + @Override + public void setPropertyValue(@NotNull String string, @Nullable String string1) { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public List getPropertyRoles() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + List allProperties = concept.getAllProperties(); + return ListSequence.fromList(allProperties).select(new ISelector() { + public String select(IProperty it) { + return it.getName(); + } + }).toListSequence(); + } + @NotNull + @Override + public List getReferenceRoles() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + List allReferenceLinks = concept.getAllReferenceLinks(); + return ListSequence.fromList(allReferenceLinks).select(new ISelector() { + public String select(IReferenceLink it) { + return it.getName(); + } + }).toListSequence(); + } + + public static class NodeReference implements INodeReference { + private SModuleReference userModuleReference; + private SModuleId usedModuleId; + + public NodeReference(SModuleReference userModuleReference, SModuleId usedModuleId) { + this.userModuleReference = userModuleReference; + this.usedModuleId = usedModuleId; + } + + @Nullable + @Override + public INode resolveNode(@Nullable IArea area) { + SRepository repo = null; + if (area != null) { + List areas = area.collectAreas(); + repo = ListSequence.fromList(areas).ofType(MPSArea.class).select(new ISelector() { + public SRepository select(MPSArea it) { + return it.getRepository(); + } + }).where(new NotNullWhereFilter()).first(); + } + if (repo == null) { + repo = MPSModuleRepository.getInstance(); + } + SModule user = userModuleReference.resolve(repo); + if (user == null) { + return null; + } + + return new SModuleAsNode(user).findDependency(this.usedModuleId); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if (Objects.equals(this.userModuleReference, that.userModuleReference)) { + return false; + } + if (Objects.equals(this.usedModuleId, that.usedModuleId)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((userModuleReference != null ? ((Object) userModuleReference).hashCode() : 0)); + result = 11 * result + ((usedModuleId != null ? ((Object) usedModuleId).hashCode() : 0)); + return result; + } + } + + private static final class CONCEPTS { + /*package*/ static final SConcept ModuleDependency$kc = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529916fL, "org.modelix.model.repositoryconcepts.structure.ModuleDependency"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink dependencies$vC8r = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299179L, "dependencies"); + } + + private static final class PROPS { + /*package*/ static final SProperty explicit$yR_K = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529916fL, 0x1e9fde9535315265L, "explicit"); + /*package*/ static final SProperty name$Ahsh = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529916fL, 0x1e9fde9535299175L, "name"); + /*package*/ static final SProperty reexport$AblR = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529916fL, 0x1e9fde9535299170L, "reexport"); + /*package*/ static final SProperty uuid$AbNT = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529916fL, 0x1e9fde9535299172L, "uuid"); + /*package*/ static final SProperty version$yXGa = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529916fL, 0x1e9fde953531526aL, "version"); + /*package*/ static final SProperty scope$mJmq = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529916fL, 0x751b3543f508b8f9L, "scope"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSModelAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSModelAdapter.java new file mode 100644 index 00000000..071aab62 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSModelAdapter.java @@ -0,0 +1,198 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SModel; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.module.SRepository; +import org.jetbrains.mps.openapi.model.SNodeAccessListener; +import org.jetbrains.mps.openapi.model.SNodeChangeListener; +import org.jetbrains.mps.openapi.model.SModelListener; +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.model.SNodeId; +import org.jetbrains.mps.openapi.model.SModelId; +import org.jetbrains.mps.openapi.persistence.ModelRoot; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.model.SModelName; +import org.jetbrains.mps.openapi.model.SModelReference; +import jetbrains.mps.smodel.MPSModuleRepository; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.mps.openapi.persistence.DataSource; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SContainmentLink; + +public class NodeToSModelAdapter implements SModel { + + public static SModel wrap(INode node, SRepository repository) { + if (node == null) { + return null; + } + return new NodeToSModelAdapter(node, repository); + } + + private INode node; + private SRepository repository; + + protected NodeToSModelAdapter(INode node, SRepository repository) { + this.node = node; + this.repository = repository; + if (!(node.getConcept().isSubConceptOf(SConceptAdapter.wrap(CONCEPTS.Model$2P)))) { + throw new RuntimeException("Not a model: " + node.getConcept()); + } + } + + @Override + public void addAccessListener(SNodeAccessListener listener) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void addChangeListener(SNodeChangeListener listener) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void addModelListener(SModelListener listener) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void addRootNode(SNode node) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public SNode createNode(@NotNull SConcept concept) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public SNode createNode(@NotNull SConcept concept, @Nullable SNodeId id) { + throw new UnsupportedOperationException("Not implemented"); + } + @NotNull + @Override + public SModelId getModelId() { + throw new UnsupportedOperationException("Not implemented"); + } + @Deprecated + @Override + public String getModelName() { + return getName().getValue(); + } + @Override + public ModelRoot getModelRoot() { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public SModule getModule() { + return NodeToSModuleAdapter.wrap(node.getParent(), repository); + } + @NotNull + @Override + public SModelName getName() { + return new SModelName(node.getPropertyValue(PROPS.name$MnvL.getName())); + } + @Override + public SNode getNode(SNodeId id) { + throw new UnsupportedOperationException("Not implemented"); + } + @NotNull + @Override + public Iterable getProblems() { + throw new UnsupportedOperationException("Not implemented"); + } + @NotNull + @Override + public SModelReference getReference() { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public SRepository getRepository() { + return (repository != null ? repository : MPSModuleRepository.getInstance()); + } + @Override + public Iterable getRootNodes() { + Iterable rootNodes = node.getChildren(LINKS.rootNodes$jxXY.getName()); + return Sequence.fromIterable(rootNodes).select(new ISelector() { + public SNode select(INode it) { + SNode adapter = NodeToSNodeAdapter.wrap(it); + ((NodeToSNodeAdapter) adapter).setModelMode(EModelMode.ADAPTER); + return adapter; + } + }); + } + @NotNull + @Override + public DataSource getSource() { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public boolean isLoaded() { + return true; + } + @Override + public boolean isReadOnly() { + return true; + } + @Override + public void load() { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void removeAccessListener(SNodeAccessListener listener) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void removeChangeListener(SNodeChangeListener listener) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void removeModelListener(SModelListener listener) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void removeRootNode(SNode node) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void unload() { + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeToSModelAdapter that = (NodeToSModelAdapter) o; + if ((node != null ? !(node.equals(that.node)) : that.node != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((node != null ? ((Object) node).hashCode() : 0)); + return result; + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Model$2P = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, "org.modelix.model.repositoryconcepts.structure.Model"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink rootNodes$jxXY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x69652614fd1c514L, "rootNodes"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSModuleAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSModuleAdapter.java new file mode 100644 index 00000000..002fddda --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSModuleAdapter.java @@ -0,0 +1,136 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.module.SModule; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.module.SRepository; +import org.jetbrains.mps.openapi.module.SModuleListener; +import org.jetbrains.mps.openapi.module.SDependency; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.module.SModuleFacet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.model.SModelId; +import org.jetbrains.mps.openapi.persistence.ModelRoot; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.mps.openapi.module.SModuleId; +import org.jetbrains.mps.openapi.module.SModuleReference; +import jetbrains.mps.smodel.MPSModuleRepository; +import java.util.Set; +import org.jetbrains.mps.openapi.language.SLanguage; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; + +public class NodeToSModuleAdapter implements SModule { + + public static SModule wrap(INode node, SRepository repository) { + if (node == null) { + return null; + } + return new NodeToSModuleAdapter(node, repository); + } + + private INode node; + private SRepository repository; + + protected NodeToSModuleAdapter(INode node, SRepository repository) { + this.node = node; + this.repository = repository; + if (!(node.getConcept().isSubConceptOf(SConceptAdapter.wrap(CONCEPTS.Module$4i)))) { + throw new RuntimeException("Not a module: " + node.getConcept()); + } + } + + @Override + public void addModuleListener(SModuleListener listener) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public Iterable getDeclaredDependencies() { + throw new UnsupportedOperationException("Not implemented"); + } + @Nullable + @Override + public T getFacet(@NotNull Class aClass) { + throw new UnsupportedOperationException("Not implemented"); + } + @NotNull + @Override + public Iterable getFacets() { + throw new UnsupportedOperationException("Not implemented"); + } + @Nullable + @Override + public SModel getModel(SModelId id) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public Iterable getModelRoots() { + throw new UnsupportedOperationException("Not implemented"); + } + @NotNull + @Override + public Iterable getModels() { + Iterable models = node.getChildren(LINKS.models$h3QT.getName()); + return Sequence.fromIterable(models).select(new ISelector() { + public SModel select(INode it) { + SModel adapter = NodeToSModelAdapter.wrap(it, repository); + return adapter; + } + }); + } + @Override + public SModuleId getModuleId() { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public String getModuleName() { + return node.getPropertyValue(PROPS.name$MnvL.getName()); + } + @NotNull + @Override + public SModuleReference getModuleReference() { + throw new UnsupportedOperationException("Not implemented"); + } + @Nullable + @Override + public SRepository getRepository() { + return (repository != null ? repository : MPSModuleRepository.getInstance()); + } + @Override + public Set getUsedLanguages() { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public int getUsedLanguageVersion(@NotNull SLanguage language) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public boolean isPackaged() { + return false; + } + @Override + public boolean isReadOnly() { + return true; + } + @Override + public void removeModuleListener(SModuleListener listener) { + throw new UnsupportedOperationException("Not implemented"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink models$h3QT = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x69652614fd1c512L, "models"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSNodeAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSNodeAdapter.java new file mode 100644 index 00000000..6fb6ae00 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/NodeToSNodeAdapter.java @@ -0,0 +1,718 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SNode; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.model.api.ContextValue; +import java.util.Map; +import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.module.SRepository; +import com.google.common.collect.MapMaker; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import jetbrains.mps.util.Computable; +import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.model.SModel; +import org.modelix.model.api.NodeUtilKt; +import org.jetbrains.mps.openapi.model.SNodeId; +import org.jetbrains.mps.openapi.model.SNodeReference; +import org.jetbrains.mps.openapi.language.SConcept; +import org.modelix.model.api.IConcept; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import jetbrains.mps.lang.core.behavior.BaseConcept__BehaviorDescriptor; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.modelix.model.api.INodeKt; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import org.jetbrains.mps.openapi.model.SReference; +import org.jetbrains.mps.openapi.model.ResolveInfo; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import org.jetbrains.mps.openapi.language.SProperty; +import java.util.Objects; +import java.util.Collections; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.util.IterableUtil; +import org.jetbrains.mps.openapi.model.SModelReference; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SInterfaceConcept; + +public class NodeToSNodeAdapter implements SNode { + private static final Logger LOG = LogManager.getLogger(NodeToSNodeAdapter.class); + + private static ContextValue currentCache = new ContextValue(); + public static class InstancesCache { + public InstancesCache() { + } + private final Map, NodeToSNodeAdapter> instances = new MapMaker().weakValues().makeMap(); + } + + public static void runWithCache(InstancesCache cache, final Runnable runnable) { + currentCache.computeWith(cache, new Function0() { + public Unit invoke() { + runnable.run(); + return Unit.INSTANCE; + } + }); + } + + public static T computeWithCache(InstancesCache cache, final Computable computable) { + return currentCache.computeWith(cache, new Function0() { + public T invoke() { + return computable.compute(); + } + }); + } + + private static NodeToSNodeAdapter getInstance(INode node, SRepository repository) { + InstancesCache cache = currentCache.getValue(); + if (cache == null) { + return new NodeToSNodeAdapter(node, repository); + } + + Tuples._2 key = MultiTuple.from(node, repository); + NodeToSNodeAdapter instance = cache.instances.get(key); + if (instance == null) { + instance = new NodeToSNodeAdapter(node, repository); + cache.instances.put(key, instance); + } + return instance; + } + + public static void clearInstancesCache() { + InstancesCache cache = currentCache.getValue(); + if (cache != null) { + cache.instances.clear(); + } + } + + public static SNode wrap(INode nodeToWrap) { + return wrap(nodeToWrap, null); + } + + public static SNode wrap(INode nodeToWrap, SRepository repository) { + if (nodeToWrap == null) { + return null; + } + if (nodeToWrap instanceof SNodeToNodeAdapter) { + return ((SNodeToNodeAdapter) nodeToWrap).getWrapped(); + } + return getInstance(nodeToWrap, repository); + } + + public static SNode wrap(SNode nodeToWrap) { + // Makes code generation easier. wrap can always be applied to ensure a value is an SNode. + return nodeToWrap; + } + + private INode node; + private SRepository repository; + private Object[] userObjects = null; + private NodeReference nodeReference = new NodeReference(); + private NodeId nodeId = new NodeId(); + private EModelMode modelMode = EModelMode.NULL; + + protected NodeToSNodeAdapter(INode node1, SRepository repository) { + if (node1.getConcept() == null) { + throw new RuntimeException("Node has no concept: " + node1); + } + node = node1; + this.repository = repository; + } + + public void setModelMode(@NotNull EModelMode mode) { + this.modelMode = mode; + } + + protected SNode wrap_(INode nodeToWrap) { + SNode wrapped = wrap(nodeToWrap, repository); + if (wrapped instanceof NodeToSNodeAdapter) { + ((NodeToSNodeAdapter) wrapped).setModelMode(modelMode); + } + return wrapped; + } + + public INode getWrapped() { + return node; + } + + @Nullable + @Override + public SModel getModel() { + switch (modelMode) { + case NULL: + return null; + case ADAPTER: + INode modelNode = NodeUtilKt.getAncestor(this.node, SConceptAdapter.wrap(CONCEPTS.Model$2P), false); + if (modelNode == null) { + return null; + } + return NodeToSModelAdapter.wrap(modelNode, repository); + default: + throw new RuntimeException("Unknown mode: " + modelMode); + } + } + @Override + public SNodeId getNodeId() { + return nodeId; + } + @NotNull + @Override + public SNodeReference getReference() { + return nodeReference; + } + @NotNull + @Override + public SConcept getConcept() { + IConcept concept = node.getConcept(); + if (concept instanceof SConceptAdapter) { + return (SConcept) ((SConceptAdapter) concept).getAdapted(); + } + SAbstractConcept sConcept = BootstrapConceptMappings.INSTANCE.getSConcept(concept); + if (sConcept instanceof SConcept) { + return (SConcept) sConcept; + } + return CONCEPTS.BaseConcept$gP; + } + @Override + public boolean isInstanceOfConcept(@NotNull SAbstractConcept concept) { + return getConcept().isSubConceptOf(concept); + } + @Override + public String getPresentation() { + SNode snode = this; + String presentation = null; + try { + presentation = BaseConcept__BehaviorDescriptor.getPresentation_idhEwIMiw.invoke(snode); + } catch (Exception ex) { + if (LOG.isDebugEnabled()) { + LOG.debug("", ex); + } + } + try { + if (presentation == null && this.isInstanceOfConcept(CONCEPTS.INamedConcept$Kd)) { + presentation = getProperty(PROPS.name$MnvL); + } + } catch (Exception ex) { + if (LOG.isDebugEnabled()) { + LOG.debug("", ex); + } + } + if (presentation == null) { + presentation = toString(); + } + return presentation; + } + @Nullable + @Override + public String getName() { + return node.getPropertyValue("name"); + } + @Override + public void addChild(@NotNull SContainmentLink link, @NotNull SNode child) { + INodeKt.moveChild(node, new SContainmentLinkAdapter(link), -1, SNodeToNodeAdapter.wrap(child)); + } + @Override + public void insertChildBefore(@NotNull SContainmentLink link, @NotNull SNode child, @Nullable SNode anchor) { + if (anchor == null) { + addChild(link, child); + return; + } + Iterable children = (Iterable) getChildren(link); + int index = Sequence.fromIterable(children).indexOf(anchor); + INodeKt.moveChild(this.node, new SContainmentLinkAdapter(link), index, SNodeToNodeAdapter.wrap(child)); + } + @Override + public void insertChildAfter(@NotNull SContainmentLink link, @NotNull SNode child, @Nullable SNode anchor) { + if (anchor == null) { + addChild(link, child); + return; + } + Iterable children = (Iterable) getChildren(link); + int index = Sequence.fromIterable(children).indexOf(anchor); + INodeKt.moveChild(this.node, new SContainmentLinkAdapter(link), index + 1, SNodeToNodeAdapter.wrap(child)); + + } + @Override + public void removeChild(@NotNull SNode node) { + this.node.removeChild(SNodeToNodeAdapter.wrap(node)); + } + @Override + public void delete() { + node.getParent().removeChild(node); + } + @Nullable + @Override + public SNode getParent() { + INode parent = node.getParent(); + if (parent == null) { + return null; + } + if (parent.getConcept() == null) { + return null; + } + SNode result = wrap_(parent); + return result; + } + @NotNull + @Override + public SNode getContainingRoot() { + INode n1; + INode n2 = node; + do { + n1 = n2; + n2 = n1.getParent(); + } while (n2 != null); + return wrap_(n1); + } + @Nullable + @Override + public SContainmentLink getContainmentLink() { + SContainmentLinkAdapter link = as_r4r1yj_a0a0a84(INodeKt.getContainmentLink(this.node), SContainmentLinkAdapter.class); + return (link == null ? null : link.getLink()); + } + @Nullable + @Override + public SNode getFirstChild() { + Iterable allChildren = node.getAllChildren(); + return wrap_(Sequence.fromIterable(allChildren).first()); + } + @Nullable + @Override + public SNode getLastChild() { + Iterable allChildren = node.getAllChildren(); + return wrap_(Sequence.fromIterable(allChildren).last()); + } + @Nullable + @Override + public SNode getPrevSibling() { + INode parent = node.getParent(); + if (parent == null) { + return null; + } + INode sibling1 = null; + INode sibling2 = null; + for (INode sibling : Sequence.fromIterable(parent.getAllChildren())) { + sibling1 = sibling2; + sibling2 = sibling; + if (node.equals(sibling2)) { + SNode result = wrap_(sibling1); + return result; + } + } + return null; + } + @Nullable + @Override + public SNode getNextSibling() { + INode parent = node.getParent(); + if (parent == null) { + return null; + } + INode sibling1 = null; + INode sibling2 = null; + for (INode sibling : Sequence.fromIterable(parent.getAllChildren())) { + sibling1 = sibling2; + sibling2 = sibling; + if (node.equals(sibling1)) { + SNode result = wrap_(sibling2); + return result; + } + } + return null; + } + @NotNull + @Override + public Iterable getChildren(SContainmentLink link) { + Iterable children = INodeKt.getChildren(this.node, new SContainmentLinkAdapter(link)); + return Sequence.fromIterable(children).select(new ISelector() { + public SNode select(INode it) { + return wrap_(it); + } + }); + } + @NotNull + @Override + public Iterable getChildren() { + Iterable allChildren = node.getAllChildren(); + return Sequence.fromIterable(allChildren).select(new ISelector() { + public SNode select(INode it) { + return wrap_(it); + } + }); + + } + @Override + public void setReferenceTarget(@NotNull SReferenceLink link, @Nullable SNode target) { + INodeKt.setReferenceTarget(this.node, new SReferenceLinkAdapter(link), SNodeToNodeAdapter.wrap(target)); + } + @Nullable + @Override + public SNode getReferenceTarget(@NotNull SReferenceLink link) { + return wrap_(INodeKt.getReferenceTarget(this.node, new SReferenceLinkAdapter(link))); + } + @Nullable + @Override + public SReference getReference(@NotNull final SReferenceLink link) { + return new Reference(link); + } + @Override + public void setReference(@NotNull SReferenceLink link, @Nullable SReference reference) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void setReference(@NotNull SReferenceLink link, ResolveInfo info) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void setReference(@NotNull SReferenceLink link, @NotNull SNodeReference reference) { + throw new UnsupportedOperationException("Not implemented"); + } + @Override + public void dropReference(@NotNull SReferenceLink link) { + throw new UnsupportedOperationException("Not implemented"); + } + @NotNull + @Override + public Iterable getReferences() { + Iterable links = SConceptAdapter.unwrap(node.getConcept()).getReferenceLinks(); + return Sequence.fromIterable(links).where(new IWhereFilter() { + public boolean accept(SReferenceLink it) { + return getReferenceTarget(it) != null; + } + }).select(new ISelector() { + public Reference select(SReferenceLink it) { + return new Reference(it); + } + }); + } + @NotNull + @Override + public Iterable getProperties() { + Iterable allProperties = SConceptAdapter.unwrap(node.getConcept()).getProperties(); + return Sequence.fromIterable(allProperties).where(new IWhereFilter() { + public boolean accept(SProperty it) { + return getProperty(it) != null; + } + }); + } + @Override + public boolean hasProperty(@NotNull SProperty property) { + return getProperty(property) != null; + } + @Nullable + @Override + public String getProperty(@NotNull SProperty property) { + return INodeKt.getPropertyValue(this.node, new SPropertyAdapter(property)); + } + @Override + public void setProperty(@NotNull SProperty property, @Nullable String value) { + INodeKt.setPropertyValue(this.node, new SPropertyAdapter(property), value); + } + @Override + public Object getUserObject(Object key) { + if (userObjects != null) { + for (int i = 0; i < userObjects.length; i += 2) { + if (Objects.equals(userObjects[i], key)) { + return userObjects[i + 1]; + } + } + } + return null; + } + @Override + public void putUserObject(Object key, @Nullable Object value) { + if (userObjects != null) { + for (int i = 0; i < userObjects.length; i += 2) { + if (Objects.equals(userObjects[i], key)) { + userObjects[i + 1] = value; + return; + } + } + + Object[] newArray = new Object[userObjects.length + 2]; + System.arraycopy(userObjects, 0, newArray, 0, userObjects.length); + newArray[newArray.length - 2] = key; + newArray[newArray.length - 1] = value; + userObjects = newArray; + } else { + userObjects = new Object[]{key, value}; + } + } + @Override + public Iterable getUserObjectKeys() { + if (userObjects == null) { + return Collections.emptyList(); + } + List result = ListSequence.fromList(new ArrayList(userObjects.length / 2)); + for (int i = 0; i < userObjects.length; i += 2) { + ListSequence.fromList(result).addElement(userObjects[i]); + } + return result; + } + @Deprecated + @Override + public String getRoleInParent() { + return check_r4r1yj_a0a96(getContainmentLink(), this); + } + @Deprecated + @Override + public boolean hasProperty(String name) { + return hasProperty(findProperty(name)); + } + @Deprecated + @Override + public String getProperty(String string) { + return getProperty(findProperty(string)); + } + @Deprecated + @Override + public void setProperty(String string, String string1) { + setProperty(findProperty(string), string1); + } + @Deprecated + @Override + public Iterable getPropertyNames() { + Iterable properties = getProperties(); + return Sequence.fromIterable(properties).select(new ISelector() { + public String select(SProperty it) { + return it.getName(); + } + }); + } + @Deprecated + @Override + public void setReferenceTarget(String string, @Nullable SNode node) { + setReferenceTarget(findReferenceLink(string), node); + } + @Deprecated + @Override + public SNode getReferenceTarget(String role) { + return getReferenceTarget(findReferenceLink(role)); + } + protected SReferenceLink findReferenceLink(final String name) { + Iterable links = getConcept().getReferenceLinks(); + SReferenceLink link = Sequence.fromIterable(links).findFirst(new IWhereFilter() { + public boolean accept(SReferenceLink it) { + return Objects.equals(it.getName(), name); + } + }); + if (link == null) { + throw new RuntimeException(getConcept().getName() + " doesn't have a reference link '" + name + "'"); + } + return link; + } + protected SContainmentLink findChildLink(final String name) { + Iterable links = getConcept().getContainmentLinks(); + SContainmentLink link = Sequence.fromIterable(links).findFirst(new IWhereFilter() { + public boolean accept(SContainmentLink it) { + return Objects.equals(it.getName(), name); + } + }); + if (link == null) { + throw new RuntimeException(getConcept().getName() + " doesn't have a child link '" + name + "'"); + } + return link; + } + protected SProperty findProperty(final String name) { + Iterable properties = getConcept().getProperties(); + SProperty property = Sequence.fromIterable(properties).findFirst(new IWhereFilter() { + public boolean accept(SProperty it) { + return Objects.equals(it.getName(), name); + } + }); + if (property == null) { + throw new RuntimeException(getConcept().getName() + " doesn't have a property '" + name + "'"); + } + return property; + } + @Deprecated + @Override + public SReference getReference(String role) { + return getReference(findReferenceLink(role)); + } + @Deprecated + @Override + public void setReference(String string, @Nullable SReference reference) { + setReference(findReferenceLink(string), reference); + } + @Deprecated + @Override + public void insertChildBefore(String role, SNode newChild, @Nullable SNode anchor) { + SContainmentLink link = findChildLink(role); + Iterable children = IterableUtil.asIterable(node.getChildren(role).iterator()); + int index = -1; + if (anchor != null) { + index = Sequence.fromIterable(children).indexOf(SNodeToNodeAdapter.wrap(anchor)); + if (index == -1) { + throw new RuntimeException(anchor + " is not a child of " + node); + } + } + INodeKt.addNewChild(this.node, new SContainmentLinkAdapter(link), index, SConceptAdapter.wrap(newChild.getConcept())); + } + @Deprecated + @Override + public void addChild(String string, SNode node) { + addChild(findChildLink(string), node); + } + @Deprecated + @Override + @NotNull + public List getChildren(String string) { + Iterable children = (Iterable) getChildren(findChildLink(string)); + return Sequence.fromIterable(children).toListSequence(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeToSNodeAdapter that = (NodeToSNodeAdapter) o; + if ((node != null ? !(node.equals(that.node)) : that.node != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((node != null ? ((Object) node).hashCode() : 0)); + return result; + } + + @Override + public String toString() { + return "NodeToSNodeAdapter[" + this.node + "]"; + } + + public class NodeReference implements SNodeReference { + @Nullable + @Override + public SNode resolve(SRepository repository) { + return NodeToSNodeAdapter.this; + } + + @Nullable + @Override + public SModelReference getModelReference() { + return null; + } + + @Override + public SNodeId getNodeId() { + return nodeId; + } + @Override + public String toString() { + return ":" + node.getReference().toString(); + } + @Override + public int hashCode() { + return NodeToSNodeAdapter.this.hashCode(); + } + @Override + public boolean equals(Object otherObject) { + if (otherObject instanceof NodeReference) { + NodeReference otherRef = ((NodeReference) otherObject); + return getNode().equals(otherRef.getNode()); + } else { + return false; + } + } + public NodeToSNodeAdapter getNode() { + return NodeToSNodeAdapter.this; + } + } + + public class NodeId implements SNodeId { + @Override + public String getType() { + return "shadowmodelsAdapter"; + } + @Override + public String toString() { + return ":" + node.getReference().toString(); + } + } + + public class Reference implements SReference { + private SReferenceLink link; + public Reference(SReferenceLink link) { + this.link = link; + } + @Deprecated + public String getRole() { + return getLink().getName(); + } + public SReferenceLink getLink() { + return link; + } + public SNode getSourceNode() { + return NodeToSNodeAdapter.this; + } + public SNode getTargetNode() { + return getReferenceTarget(link); + } + public SNodeReference getTargetNodeReference() { + SNode targetNode = getTargetNode(); + return check_r4r1yj_a1a6rd(targetNode); + } + @Nullable + public SModelReference getTargetSModelReference() { + SNode targetNode = getTargetNode(); + SModel model = check_r4r1yj_a0b0h59(targetNode); + return (model == null ? null : model.getReference()); + } + @Nullable + public SNodeId getTargetNodeId() { + return getTargetNode().getNodeId(); + } + + } + + private static String check_r4r1yj_a0a96(SContainmentLink checkedDotOperand, NodeToSNodeAdapter checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getName(); + } + return null; + } + private static SNodeReference check_r4r1yj_a1a6rd(SNode checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getReference(); + } + return null; + } + private static SModel check_r4r1yj_a0b0h59(SNode checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModel(); + } + return null; + } + private static T as_r4r1yj_a0a0a84(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Model$2P = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, "org.modelix.model.repositoryconcepts.structure.Model"); + /*package*/ static final SConcept BaseConcept$gP = MetaAdapterFactory.getConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, "jetbrains.mps.lang.core.structure.BaseConcept"); + /*package*/ static final SInterfaceConcept INamedConcept$Kd = MetaAdapterFactory.getInterfaceConcept(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, "jetbrains.mps.lang.core.structure.INamedConcept"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ProjectAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ProjectAsNode.java new file mode 100644 index 00000000..9d31aa6e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ProjectAsNode.java @@ -0,0 +1,168 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import jetbrains.mps.project.MPSProject; +import org.modelix.model.api.INode; +import jetbrains.mps.internal.collections.runtime.Sequence; +import java.util.Collections; +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConcept; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.modelix.model.api.INodeReference; +import java.util.Objects; +import org.modelix.model.area.IArea; +import java.util.List; +import jetbrains.mps.project.Project; +import jetbrains.mps.project.ProjectManager; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; + +public class ProjectAsNode extends TreeElementAsNode { + private static TreeElementAsNode.IChildAccessor modulesAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(MPSProject project) { + return Sequence.fromIterable(Collections.emptyList()); + } + }; + private static TreeElementAsNode.IChildAccessor projectModulesAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(final MPSProject project) { + Iterable modules = project.getProjectModules(); + return Sequence.fromIterable(modules).select(new ISelector() { + public ProjectModuleAsNode select(SModule it) { + return new ProjectModuleAsNode(project, it); + } + }); + } + }; + private TreeElementAsNode.IPropertyAccessor nameAccessor = new TreeElementAsNode.IPropertyAccessor() { + @Override + public String get(MPSProject element) { + return element.getName(); + } + + @Override + public String set(MPSProject element, String value) { + throw new UnsupportedOperationException("readonly"); + } + }; + public ProjectAsNode(@NotNull MPSProject element) { + super(element); + } + @Nullable + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.Project$An); + } + @Nullable + @Override + public INode getParent() { + return new SRepositoryAsNode(MPSModuleRepository.getInstance()); + } + @NotNull + @Override + public INodeReference getReference() { + return new NodeReference(getElement()); + } + @Nullable + @Override + public String getRoleInParent() { + return LINKS.projects$NW07.getName(); + } + @Override + protected TreeElementAsNode.IChildAccessor getChildAccessor(String role) { + if (role.equals(LINKS.modules$Bi3g.getName())) { + return modulesAccessor; + } + if (role.equals(LINKS.projectModules$VXcy.getName())) { + return projectModulesAccessor; + } + return super.getChildAccessor(role); + } + @Override + protected TreeElementAsNode.IPropertyAccessor getPropertyAccessor(String role) { + if (Objects.equals(role, PROPS.name$MnvL.getName())) { + return this.nameAccessor; + } + return super.getPropertyAccessor(role); + } + + public static class NodeReference implements INodeReference { + private String projectName; + private String path; + + public NodeReference(MPSProject project) { + this.projectName = project.getName(); + this.path = project.getProject().getPresentableUrl(); + } + + public NodeReference(String projectName, String path) { + this.projectName = projectName; + this.path = path; + } + + public String getProjectName() { + return this.projectName; + } + + @Nullable + @Override + public ProjectAsNode resolveNode(@Nullable IArea area) { + List projects = ProjectManager.getInstance().getOpenedProjects(); + MPSProject project = ListSequence.fromList(projects).ofType(MPSProject.class).findFirst(new IWhereFilter() { + public boolean accept(MPSProject it) { + return Objects.equals(it.getName(), projectName) && Objects.equals(it.getProject().getPresentableUrl(), path); + } + }); + return (project == null ? null : new ProjectAsNode(project)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if ((path != null ? !(((Object) path).equals(that.path)) : that.path != null)) { + return false; + } + if ((projectName != null ? !(((Object) projectName).equals(that.projectName)) : that.projectName != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((path != null ? String.valueOf(path).hashCode() : 0)); + result = 31 * result + ((projectName != null ? String.valueOf(projectName).hashCode() : 0)); + return result; + } + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Project$An = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, "org.modelix.model.repositoryconcepts.structure.Project"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink projects$NW07 = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x620a8558361d3e0cL, "projects"); + /*package*/ static final SContainmentLink modules$Bi3g = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, 0x37a0917d689de9e2L, "modules"); + /*package*/ static final SContainmentLink projectModules$VXcy = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, 0x3a4fe9e427e83268L, "projectModules"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ProjectModuleAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ProjectModuleAsNode.java new file mode 100644 index 00000000..a61af18e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ProjectModuleAsNode.java @@ -0,0 +1,160 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; +import jetbrains.mps.project.MPSProject; +import org.jetbrains.mps.openapi.module.SModule; +import org.modelix.model.api.INode; +import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; +import java.util.Objects; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConcept; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.api.INodeReference; +import org.jetbrains.mps.openapi.module.SModuleReference; +import org.modelix.model.area.IArea; +import jetbrains.mps.project.structure.project.ModulePath; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SConcept; + +public class ProjectModuleAsNode extends TreeElementAsNode> { + private TreeElementAsNode.IReferenceAccessor> moduleAccessor = new TreeElementAsNode.IReferenceAccessor>() { + @Override + public INode get(Tuples._2 element) { + return new SModuleAsNode(element._1()); + } + + @Override + public INode set(Tuples._2 element, INode target) { + throw new UnsupportedOperationException("readonly"); + } + }; + private TreeElementAsNode.IPropertyAccessor> virtualFolderAccessor = new TreeElementAsNode.IPropertyAccessor>() { + @Override + public String get(Tuples._2 element) { + return check_9jclrw_a0a0a0a1(element._0().getPath(element._1())); + } + + @Override + public String set(Tuples._2 element, String value) { + element._0().setVirtualFolder(element._1(), value); + return value; + } + }; + + public ProjectModuleAsNode(MPSProject project, SModule module) { + super(MultiTuple.from(project, module)); + } + + @Override + protected TreeElementAsNode.IReferenceAccessor> getReferenceAccessor(String role) { + if (Objects.equals(role, LINKS.module$DFjI.getName())) { + return this.moduleAccessor; + } + return super.getReferenceAccessor(role); + } + @Override + protected TreeElementAsNode.IPropertyAccessor> getPropertyAccessor(String role) { + if (Objects.equals(role, PROPS.virtualFolder$dgnn.getName())) { + return this.virtualFolderAccessor; + } + return super.getPropertyAccessor(role); + } + @Nullable + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.ProjectModule$uf); + } + @Override + public INode getParent() { + return new ProjectAsNode(getElement()._0()); + } + @NotNull + @Override + public INodeReference getReference() { + return new NodeReference((ProjectAsNode.NodeReference) getParent().getReference(), getElement()._1().getModuleReference()); + } + @Nullable + @Override + public String getRoleInParent() { + return LINKS.modules$Bi3g.getName(); + } + + public static class NodeReference implements INodeReference { + private ProjectAsNode.NodeReference projectRef; + private SModuleReference moduleRef; + + public NodeReference(ProjectAsNode.NodeReference projectRef, SModuleReference moduleRef) { + this.projectRef = projectRef; + this.moduleRef = moduleRef; + } + + public SModuleReference getModuleRef() { + return this.moduleRef; + } + + public ProjectAsNode.NodeReference getProjectRef() { + return this.projectRef; + } + + @Nullable + @Override + public INode resolveNode(@Nullable IArea area) { + MPSProject project = projectRef.resolveNode(area).getElement(); + SModule module = moduleRef.resolve(project.getRepository()); + return new ProjectModuleAsNode(project, module); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if ((moduleRef != null ? !(moduleRef.equals(that.moduleRef)) : that.moduleRef != null)) { + return false; + } + if ((projectRef != null ? !(projectRef.equals(that.projectRef)) : that.projectRef != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((moduleRef != null ? ((Object) moduleRef).hashCode() : 0)); + result = 31 * result + ((projectRef != null ? ((Object) projectRef).hashCode() : 0)); + return result; + } + } + + private static String check_9jclrw_a0a0a0a1(ModulePath checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getVirtualFolder(); + } + return null; + } + + private static final class LINKS { + /*package*/ static final SReferenceLink module$DFjI = MetaAdapterFactory.getReferenceLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x5040008087d5d3d4L, 0x5040008087d5d3edL, "module"); + /*package*/ static final SContainmentLink modules$Bi3g = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, 0x37a0917d689de9e2L, "modules"); + } + + private static final class PROPS { + /*package*/ static final SProperty virtualFolder$dgnn = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x3a4fe9e427e83264L, 0x3a4fe9e427e83265L, "virtualFolder"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept ProjectModule$uf = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x3a4fe9e427e83264L, "org.modelix.model.repositoryconcepts.structure.ProjectModule"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ReadOnlyPropertyAccessor.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ReadOnlyPropertyAccessor.java new file mode 100644 index 00000000..79a03777 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/ReadOnlyPropertyAccessor.java @@ -0,0 +1,11 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + + +public abstract class ReadOnlyPropertyAccessor implements TreeElementAsNode.IPropertyAccessor { + @Override + public final String set(E element, String value) { + throw new UnsupportedOperationException("This property is readonly"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SConceptAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SConceptAdapter.java new file mode 100644 index 00000000..9fabe5df --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SConceptAdapter.java @@ -0,0 +1,267 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.IConcept; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.api.IConceptReference; +import org.modelix.model.api.ConceptReference; +import jetbrains.mps.smodel.adapter.ids.MetaIdHelper; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.ILanguage; +import java.util.List; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.mps.openapi.language.SInterfaceConcept; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import java.util.Collections; +import java.util.Objects; +import org.modelix.model.api.IProperty; +import org.jetbrains.mps.openapi.language.SProperty; +import org.modelix.model.api.IChildLink; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.modelix.model.api.IReferenceLink; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; + +public class SConceptAdapter implements IConcept { + + public static SAbstractConcept unwrap(IConcept concept) { + if (concept == null) { + return null; + } + if (concept instanceof SConceptAdapter) { + return ((SConceptAdapter) concept).getAdapted(); + } + return null; + } + + public static IConcept wrap(SAbstractConcept concept) { + if (concept == null) { + return null; + } + return new SConceptAdapter(concept); + } + + private SAbstractConcept concept; + + public SConceptAdapter(SAbstractConcept concept1) { + concept = concept1; + } + + @NotNull + @Override + public IConceptReference getReference() { + return new ConceptReference(getUID()); + } + + public SAbstractConcept getAdapted() { + return concept; + } + + @Override + public boolean isAbstract() { + return concept.isAbstract(); + } + + @NotNull + @Override + public String getUID() { + return "mps:" + MetaIdHelper.getConcept(concept).serialize(); + } + + @Nullable + @Override + public ILanguage getLanguage() { + return new SLanguageAdapter(concept.getLanguage()); + } + + @NotNull + @Override + public List getDirectSuperConcepts() { + Iterable superConcepts; + if (concept instanceof SConcept) { + SConcept c = ((SConcept) concept); + Iterable superInterfaces = c.getSuperInterfaces(); + superConcepts = Sequence.fromIterable(Sequence.singleton(c.getSuperConcept())).concat(Sequence.fromIterable(superInterfaces)); + } else if (concept instanceof SInterfaceConcept) { + SInterfaceConcept c = ((SInterfaceConcept) concept); + Iterable superInterfaces = c.getSuperInterfaces(); + superConcepts = Sequence.fromIterable(superInterfaces).select(new ISelector() { + public SInterfaceConcept select(SInterfaceConcept it) { + return it; + } + }); + } else { + superConcepts = Sequence.fromIterable(Collections.emptyList()); + } + + return Sequence.fromIterable(superConcepts).select(new ISelector() { + public IConcept select(SAbstractConcept it) { + IConcept adapter = new SConceptAdapter(it); + return adapter; + } + }).toListSequence(); + } + + @NotNull + @Override + public String getLongName() { + return concept.getLanguage().getQualifiedName() + "." + concept.getName(); + } + + @NotNull + @Override + public String getShortName() { + return concept.getName(); + } + + @Override + public boolean isSubConceptOf(IConcept superConcept) { + return concept.isSubConceptOf(((SConceptAdapter) superConcept).concept); + } + + @Override + public boolean isExactly(IConcept otherConcept) { + return Objects.equals(concept, ((SConceptAdapter) otherConcept).concept); + } + + @Override + public List getAllProperties() { + Iterable properties = concept.getProperties(); + return Sequence.fromIterable(properties).select(new ISelector() { + public IProperty select(SProperty it) { + IProperty p = new SPropertyAdapter(it); + return p; + } + }).toListSequence(); + } + + @Override + public List getAllChildLinks() { + Iterable links = concept.getContainmentLinks(); + return Sequence.fromIterable(links).select(new ISelector() { + public IChildLink select(SContainmentLink it) { + IChildLink l = new SContainmentLinkAdapter(it); + return l; + } + }).toListSequence(); + } + + @Override + public List getAllReferenceLinks() { + Iterable links = concept.getReferenceLinks(); + return Sequence.fromIterable(links).select(new ISelector() { + public IReferenceLink select(SReferenceLink it) { + IReferenceLink adapter = new SReferenceLinkAdapter(it); + return adapter; + } + }).toListSequence(); + } + + @Override + public IChildLink getChildLink(final String name) { + return ListSequence.fromList(getAllChildLinks()).findFirst(new IWhereFilter() { + public boolean accept(IChildLink it) { + return Objects.equals(it.getName(), name); + } + }); + } + + @Override + public IProperty getProperty(final String name) { + return ListSequence.fromList(getAllProperties()).findFirst(new IWhereFilter() { + public boolean accept(IProperty it) { + return Objects.equals(it.getName(), name); + } + }); + } + + @Override + public IReferenceLink getReferenceLink(final String name) { + return ListSequence.fromList(getAllReferenceLinks()).findFirst(new IWhereFilter() { + public boolean accept(IReferenceLink it) { + return Objects.equals(it.getName(), name); + } + }); + } + + @NotNull + @Override + public List getOwnProperties() { + Iterable properties = concept.getProperties(); + return Sequence.fromIterable(properties).where(new IWhereFilter() { + public boolean accept(SProperty it) { + return Objects.equals(it.getOwner(), concept); + } + }).select(new ISelector() { + public IProperty select(SProperty it) { + IProperty p = new SPropertyAdapter(it); + return p; + } + }).toListSequence(); + } + + @NotNull + @Override + public List getOwnChildLinks() { + Iterable containmentLinks = concept.getContainmentLinks(); + return Sequence.fromIterable(containmentLinks).where(new IWhereFilter() { + public boolean accept(SContainmentLink it) { + return Objects.equals(it.getOwner(), concept); + } + }).select(new ISelector() { + public IChildLink select(SContainmentLink it) { + IChildLink l = new SContainmentLinkAdapter(it); + return l; + } + }).toListSequence(); + } + + @NotNull + @Override + public List getOwnReferenceLinks() { + Iterable referenceLinks = concept.getReferenceLinks(); + return Sequence.fromIterable(referenceLinks).where(new IWhereFilter() { + public boolean accept(SReferenceLink it) { + return Objects.equals(it.getOwner(), concept); + } + }).select(new ISelector() { + public IReferenceLink select(SReferenceLink it) { + IReferenceLink adapter = new SReferenceLinkAdapter(it); + return adapter; + } + }).toListSequence(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + SConceptAdapter that = (SConceptAdapter) o; + if ((concept != null ? !(concept.equals(that.concept)) : that.concept != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((concept != null ? ((Object) concept).hashCode() : 0)); + return result; + } + + @Override + public String toString() { + return concept.getName(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SContainmentLinkAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SContainmentLinkAdapter.java new file mode 100644 index 00000000..c72f77df --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SContainmentLinkAdapter.java @@ -0,0 +1,87 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.IChildLink; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.smodel.adapter.ids.MetaIdHelper; +import org.modelix.model.api.IConcept; + +public class SContainmentLinkAdapter implements IChildLink { + + private SContainmentLink link; + + public SContainmentLinkAdapter(SContainmentLink link1) { + link = link1; + } + + @NotNull + @Override + public String getUID() { + return MetaIdHelper.getAggregation(link).serialize(); + } + + @NotNull + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(link.getOwner()); + } + + public SContainmentLink getLink() { + return link; + } + + @NotNull + @Override + public String getSimpleName() { + return link.getName(); + } + + @Override + public boolean isMultiple() { + return link.isMultiple(); + } + + @Override + public String toString() { + return link.getOwner().getName() + "." + link.getName(); + } + + @NotNull + @Override + public IConcept getChildConcept() { + return getTargetConcept(); + } + @NotNull + @Override + public IConcept getTargetConcept() { + return new SConceptAdapter(link.getTargetConcept()); + } + @Override + public boolean isOptional() { + return link.isOptional(); + } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + SContainmentLinkAdapter that = (SContainmentLinkAdapter) o; + if ((link != null ? !(link.equals(that.link)) : that.link != null)) { + return false; + } + + return true; + } + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((link != null ? ((Object) link).hashCode() : 0)); + return result; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SLanguageAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SLanguageAdapter.java new file mode 100644 index 00000000..9e7da0d7 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SLanguageAdapter.java @@ -0,0 +1,68 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.ILanguage; +import org.jetbrains.mps.openapi.language.SLanguage; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.smodel.adapter.ids.MetaIdHelper; +import java.util.List; +import org.modelix.model.api.IConcept; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; + +public class SLanguageAdapter implements ILanguage { + private SLanguage language; + public SLanguageAdapter(SLanguage language) { + this.language = language; + } + + @NotNull + @Override + public String getUID() { + return MetaIdHelper.getLanguage(language).serialize(); + } + + @NotNull + @Override + public String getName() { + return language.getQualifiedName(); + } + + @NotNull + @Override + public List getConcepts() { + Iterable concepts = language.getConcepts(); + return Sequence.fromIterable(concepts).select(new ISelector() { + public IConcept select(SAbstractConcept it) { + IConcept c = new SConceptAdapter(it); + return c; + } + }).toListSequence(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + SLanguageAdapter that = (SLanguageAdapter) o; + if ((language != null ? !(language.equals(that.language)) : that.language != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((language != null ? ((Object) language).hashCode() : 0)); + return result; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SModelAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SModelAsNode.java new file mode 100644 index 00000000..1b36b15a --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SModelAsNode.java @@ -0,0 +1,299 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SModel; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.model.SNode; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.mps.openapi.model.SModelReference; +import jetbrains.mps.smodel.ModelImports; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.smodel.DefaultSModelDescriptor; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.LinkedList; +import org.jetbrains.mps.openapi.language.SLanguage; +import jetbrains.mps.internal.collections.runtime.CollectionSequence; +import org.jetbrains.mps.openapi.module.SModuleReference; +import java.util.Collections; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.area.IArea; +import org.modelix.model.api.IConcept; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.module.SModuleId; +import java.util.Objects; +import org.modelix.model.api.INodeReference; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; + +public class SModelAsNode extends TreeElementAsNode implements INode { + + private static TreeElementAsNode.IPropertyAccessor nameAccessor = new TreeElementAsNode.IPropertyAccessor() { + public String get(SModel element) { + return element.getName().getLongName(); + } + public String set(SModel element, String value) { + throw new UnsupportedOperationException("Model name is read only"); + } + }; + private static TreeElementAsNode.IPropertyAccessor stereotypeAccessor = new TreeElementAsNode.IPropertyAccessor() { + public String get(SModel element) { + return element.getName().getStereotype(); + } + public String set(SModel element, String value) { + throw new UnsupportedOperationException("Stereotype is read only"); + } + }; + private static TreeElementAsNode.IPropertyAccessor idAccessor = new TreeElementAsNode.IPropertyAccessor() { + public String get(SModel element) { + return element.getModelId().toString(); + } + public String set(SModel element, String value) { + throw new UnsupportedOperationException("Model ID is read only"); + } + }; + + private static TreeElementAsNode.IChildAccessor rootNodesAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(SModel element) { + Iterable nodes = element.getRootNodes(); + return Sequence.fromIterable(nodes).select(new ISelector() { + public INode select(SNode it) { + return SNodeToNodeAdapter.wrap(it); + } + }); + } + }; + + private static TreeElementAsNode.IChildAccessor modelImportsAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(final SModel element) { + Iterable importedModelRefs = new ModelImports(element).getImportedModels(); + Iterable importedModels = Sequence.fromIterable(importedModelRefs).select(new ISelector() { + public SModel select(SModelReference it) { + return it.resolve(element.getRepository()); + } + }).where(new NotNullWhereFilter()); + return Sequence.fromIterable(importedModels).select(new ISelector() { + public ModelImportAsNode select(SModel it) { + return new ModelImportAsNode(it, element); + } + }); + } + }; + private static TreeElementAsNode.IChildAccessor usedLanguagesAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(final SModel element) { + if (element instanceof DefaultSModelDescriptor) { + DefaultSModelDescriptor sdmd = ((DefaultSModelDescriptor) element); + List res = ListSequence.fromList(new LinkedList()); + for (SLanguage languageId : CollectionSequence.fromCollection(sdmd.importedLanguageIds())) { + int languageVersion = sdmd.getLanguageImportVersion(languageId); + ListSequence.fromList(res).addElement(new SingleLanguageDependencyAsNode(languageId.getSourceModuleReference(), languageVersion, element)); + } + for (SModuleReference devKit : ListSequence.fromList(sdmd.importedDevkits())) { + ListSequence.fromList(res).addElement(new DevKitDependencyAsNode(devKit, element)); + } + + return res; + } + return Sequence.fromIterable(Collections.emptyList()); + } + @Override + public void remove(SModel element, INode childToRemove) { + if (element instanceof DefaultSModelDescriptor) { + DefaultSModelDescriptor sdmd = ((DefaultSModelDescriptor) element); + if (childToRemove instanceof SingleLanguageDependencyAsNode) { + SingleLanguageDependencyAsNode depToRemove = ((SingleLanguageDependencyAsNode) childToRemove); + SLanguage languageToRemove = MetaAdapterFactory.getLanguage(depToRemove.getModuleReference()); + sdmd.deleteLanguageId(languageToRemove); + } else { + throw new IllegalStateException("The language to remove is not SingleLanguageDependencyAsNode. Class: " + childToRemove.getClass()); + } + } else { + throw new IllegalStateException("The model is not a DefaultSModelDescriptor. Class: " + element.getClass()); + } + } + }; + + public static SModelAsNode wrap(SModel model) { + return (model == null ? null : new SModelAsNode(model)); + } + + public SModelAsNode(@NotNull SModel model) { + super(model); + } + + @NotNull + @Override + public IArea getArea() { + return new MPSArea(getElement().getRepository()); + } + + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.Model$2P); + } + + @Override + protected TreeElementAsNode.IChildAccessor getChildAccessor(String role) { + if (role.equals(LINKS.rootNodes$jxXY.getName())) { + return rootNodesAccessor; + } + if (role.equals(LINKS.modelImports$8DOI.getName())) { + return SModelAsNode.modelImportsAccessor; + } + if (role.equals(LINKS.usedLanguages$QK4E.getName())) { + return SModelAsNode.usedLanguagesAccessor; + } + return super.getChildAccessor(role); + } + @Override + protected TreeElementAsNode.IPropertyAccessor getPropertyAccessor(String role) { + if (role.equals(PROPS.name$MnvL.getName())) { + return nameAccessor; + } + if (role.equals(PROPS.id$lDUo.getName())) { + return idAccessor; + } + if (role.equals(PROPS.stereotype$h7NZ.getName())) { + return stereotypeAccessor; + } + return super.getPropertyAccessor(role); + } + @Override + protected TreeElementAsNode.IReferenceAccessor getReferenceAccessor(String role) { + return super.getReferenceAccessor(role); + } + @Override + public INode getParent() { + return SModuleAsNode.wrap(getElement().getModule()); + } + @Override + public String getRoleInParent() { + return LINKS.models$h3QT.getName(); + } + + @Nullable + public SingleLanguageDependencyAsNode findSingleLanguageDependency(SModuleId dependencyId) { + if (this.getElement() instanceof DefaultSModelDescriptor) { + DefaultSModelDescriptor sdmd = ((DefaultSModelDescriptor) this.getElement()); + for (SLanguage entry : CollectionSequence.fromCollection(sdmd.importedLanguageIds())) { + if (Objects.equals(check_v4c8ud_a0a0b0a0y(entry.getSourceModule()), dependencyId)) { + return new SingleLanguageDependencyAsNode(entry.getSourceModuleReference(), sdmd.getLanguageImportVersion(entry), getElement()); + } + } + } + return null; + } + @Nullable + public DevKitDependencyAsNode findDevKitDependency(SModuleId dependencyId) { + if (this.getElement() instanceof DefaultSModelDescriptor) { + DefaultSModelDescriptor sdmd = ((DefaultSModelDescriptor) this.getElement()); + for (SModuleReference devKit : ListSequence.fromList(sdmd.importedDevkits())) { + if (Objects.equals(devKit.getModuleId(), dependencyId)) { + return new DevKitDependencyAsNode(devKit, getElement()); + } + } + } + return null; + } + + @NotNull + @Override + public INodeReference getReference() { + return new NodeReference(getElement().getReference()); + } + + public static class NodeReference implements INodeReference { + private SModelReference modelRef; + + public NodeReference(SModelReference modelRef) { + this.modelRef = modelRef; + } + + public SModelReference getModelRef() { + return this.modelRef; + } + + @Nullable + @Override + public SModelAsNode resolveNode(@Nullable IArea area) { + final Wrappers._T repo = new Wrappers._T(null); + if (area != null) { + List areas = area.collectAreas(); + repo.value = ListSequence.fromList(areas).ofType(MPSArea.class).select(new ISelector() { + public SRepository select(MPSArea it) { + return it.getRepository(); + } + }).where(new NotNullWhereFilter()).first(); + } + if (repo.value == null) { + repo.value = MPSModuleRepository.getInstance(); + } + final Wrappers._T resolved = new Wrappers._T(null); + if (repo.value.getModelAccess().canRead()) { + resolved.value = modelRef.resolve(repo.value); + } else { + repo.value.getModelAccess().runReadAction(new Runnable() { + public void run() { + resolved.value = modelRef.resolve(repo.value); + } + }); + } + return new SModelAsNode(resolved.value); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if (!(Objects.equals(this.modelRef, that.modelRef))) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((modelRef != null ? modelRef.hashCode() : 0)); + return result; + } + } + private static SModuleId check_v4c8ud_a0a0b0a0y(SModule checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModuleId(); + } + return null; + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Model$2P = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, "org.modelix.model.repositoryconcepts.structure.Model"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink rootNodes$jxXY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x69652614fd1c514L, "rootNodes"); + /*package*/ static final SContainmentLink modelImports$8DOI = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x58dbe6e4d4f32eb8L, "modelImports"); + /*package*/ static final SContainmentLink usedLanguages$QK4E = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x4aaf28cf2092e98eL, "usedLanguages"); + /*package*/ static final SContainmentLink models$h3QT = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x69652614fd1c512L, "models"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$lDUo = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x244b85440ee67212L, "id"); + /*package*/ static final SProperty stereotype$h7NZ = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x35307994bbd9588dL, "stereotype"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SModuleAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SModuleAsNode.java new file mode 100644 index 00000000..f538b9f6 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SModuleAsNode.java @@ -0,0 +1,451 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.smodel.tempmodel.TempModule; +import jetbrains.mps.smodel.tempmodel.TempModule2; +import java.util.List; +import jetbrains.mps.project.Project; +import jetbrains.mps.project.ProjectManager; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.project.MPSProject; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.project.structure.modules.ModuleDescriptor; +import jetbrains.mps.project.AbstractModule; +import jetbrains.mps.project.DevKit; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.model.SModel; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.jetbrains.mps.openapi.module.SModuleFacet; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import jetbrains.mps.project.facets.JavaModuleFacet; +import java.util.Collections; +import java.util.LinkedList; +import jetbrains.mps.internal.collections.runtime.IMapping; +import org.jetbrains.mps.openapi.module.SModuleReference; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import org.jetbrains.mps.openapi.language.SLanguage; +import jetbrains.mps.internal.collections.runtime.CollectionSequence; +import org.jetbrains.mps.openapi.module.SDependencyScope; +import org.jetbrains.mps.openapi.module.SModuleId; +import jetbrains.mps.project.Solution; +import jetbrains.mps.project.structure.modules.SolutionDescriptor; +import jetbrains.mps.project.structure.modules.Dependency; +import java.util.Objects; +import org.jetbrains.mps.openapi.module.SDependency; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.area.IArea; +import org.modelix.model.api.IConcept; +import org.modelix.model.api.INodeReference; +import org.jetbrains.annotations.Nullable; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.smodel.MPSModuleRepository; +import jetbrains.mps.project.structure.project.ModulePath; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; + +public class SModuleAsNode extends TreeElementAsNode { + public static boolean isTempModule(SModule module) { + return module instanceof TempModule || module instanceof TempModule2; + } + + private static TreeElementAsNode.IPropertyAccessor nameAccessor = new ReadOnlyPropertyAccessor() { + public String get(SModule element) { + return element.getModuleName(); + } + }; + + private static TreeElementAsNode.IPropertyAccessor idAccessor = new ReadOnlyPropertyAccessor() { + public String get(SModule element) { + return element.getModuleId().toString(); + } + }; + private static TreeElementAsNode.IPropertyAccessor virtualFolderAccessor = new ReadOnlyPropertyAccessor() { + public String get(final SModule element) { + List projects = ProjectManager.getInstance().getOpenedProjects(); + return ListSequence.fromList(projects).ofType(MPSProject.class).select(new ISelector() { + public String select(MPSProject it) { + return check_jbj149_a0a0a0a0b0a0a0f(it.getPath(element)); + } + }).where(new NotNullWhereFilter()).first(); + } + }; + + private static TreeElementAsNode.IPropertyAccessor moduleVersionAccessor = new ReadOnlyPropertyAccessor() { + public String get(SModule element) { + ModuleDescriptor moduleDescriptor = ((AbstractModule) element).getModuleDescriptor(); + if (element instanceof AbstractModule) { + return Integer.toString(check_jbj149_a0a0b0a0a0h(moduleDescriptor)); + } else { + return Integer.toString(0); + } + } + }; + + private static TreeElementAsNode.IPropertyAccessor compileInMPSAccessor = new ReadOnlyPropertyAccessor() { + public String get(SModule element) { + if (element instanceof DevKit) { + return Boolean.toString(false); + } + if (element instanceof AbstractModule) { + try { + return Boolean.toString(check_jbj149_a0a0a0b0a0a0j(((AbstractModule) element).getModuleDescriptor())); + } catch (UnsupportedOperationException uoe) { + return Boolean.toString(false); + } + } else { + return Boolean.toString(false); + } + } + }; + + private static TreeElementAsNode.IChildAccessor modelsAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(SModule module) { + Iterable models = module.getModels(); + return Sequence.fromIterable(models).select(new ISelector() { + public SModelAsNode select(SModel it) { + return new SModelAsNode(it); + } + }); + } + }; + + private static TreeElementAsNode.IChildAccessor facetsAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(SModule module) { + Iterable facets = module.getFacets(); + // TODO We ignore facets which are not JavaModuleFacet. In the future we may need to process those too + return Sequence.fromIterable(facets).where(new IWhereFilter() { + public boolean accept(SModuleFacet it) { + return it instanceof JavaModuleFacet; + } + }).select(new ISelector() { + public JavaModuleFacetAsNode select(SModuleFacet it) { + return new JavaModuleFacetAsNode(((JavaModuleFacet) it)); + } + }); + } + }; + + private static TreeElementAsNode.IChildAccessor dependenciesAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(SModule module) { + if (!((module instanceof AbstractModule))) { + return Sequence.fromIterable(Collections.emptyList()); + } + ModuleDescriptor moduleDescriptor = ((AbstractModule) module).getModuleDescriptor(); + List deps = ListSequence.fromList(new LinkedList()); + if (moduleDescriptor == null) { + return null; + } + for (IMapping depVersion : MapSequence.fromMap(moduleDescriptor.getDependencyVersions())) { + ListSequence.fromList(deps).addElement(new ModuleDependencyAsNode(depVersion.key(), depVersion.value(), isDirectDependency(module, depVersion.key().getModuleId()), isReexport(module, depVersion.key().getModuleId()), module, getDependencyScope(module, depVersion.key().getModuleId()))); + } + return deps; + } + }; + + private static TreeElementAsNode.IChildAccessor languageDependenciesAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(SModule module) { + if (!((module instanceof AbstractModule))) { + return Sequence.fromIterable(Collections.emptyList()); + } + ModuleDescriptor moduleDescriptor = ((AbstractModule) module).getModuleDescriptor(); + List deps = ListSequence.fromList(new LinkedList()); + if (moduleDescriptor != null) { + for (IMapping depVersion : MapSequence.fromMap(moduleDescriptor.getLanguageVersions())) { + ListSequence.fromList(deps).addElement(new SingleLanguageDependencyAsNode(depVersion.key().getSourceModuleReference(), depVersion.value(), module)); + } + for (SModuleReference devKit : CollectionSequence.fromCollection(moduleDescriptor.getUsedDevkits())) { + ListSequence.fromList(deps).addElement(new DevKitDependencyAsNode(devKit, module)); + } + } + return deps; + } + }; + + private static SDependencyScope getDependencyScope(SModule module, SModuleId moduleId) { + if (module instanceof Solution) { + // This gives slightly different results than the getDeclaredDepencies + Solution solution = ((Solution) module); + SolutionDescriptor solutionDescriptor = solution.getModuleDescriptor(); + for (Dependency dep : CollectionSequence.fromCollection(solutionDescriptor.getDependencies())) { + if (Objects.equals(dep.getModuleRef().getModuleId(), moduleId)) { + return dep.getScope(); + } + } + return null; + } + for (SDependency declaredDep : Sequence.fromIterable(module.getDeclaredDependencies())) { + if (Objects.equals(declaredDep.getTargetModule().getModuleId(), moduleId)) { + return declaredDep.getScope(); + } + } + return null; + } + private static boolean isDirectDependency(SModule module, SModuleId moduleId) { + if (module instanceof Solution) { + // This gives slightly different results than the getDeclaredDepencies + Solution solution = ((Solution) module); + SolutionDescriptor solutionDescriptor = solution.getModuleDescriptor(); + for (Dependency dep : CollectionSequence.fromCollection(solutionDescriptor.getDependencies())) { + if (Objects.equals(dep.getModuleRef().getModuleId(), moduleId)) { + return true; + } + } + return false; + } + for (SDependency declaredDep : Sequence.fromIterable(module.getDeclaredDependencies())) { + if (Objects.equals(declaredDep.getTargetModule().getModuleId(), moduleId)) { + return true; + } + } + return false; + } + + private static boolean isReexport(SModule module, SModuleId moduleId) { + for (SDependency declaredDep : Sequence.fromIterable(module.getDeclaredDependencies())) { + if (Objects.equals(declaredDep.getTargetModule().getModuleId(), moduleId)) { + return declaredDep.isReexport(); + } + } + return false; + } + + public static SModuleAsNode wrap(SModule module) { + return (module == null ? null : new SModuleAsNode(module)); + } + + public SModuleAsNode(@NotNull SModule module) { + super(module); + } + + @NotNull + @Override + public IArea getArea() { + return new MPSArea(getElement().getRepository()); + } + + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.Module$4i); + } + + @Override + protected TreeElementAsNode.IChildAccessor getChildAccessor(String role) { + if (role.equals(LINKS.models$h3QT.getName())) { + return modelsAccessor; + } + if (role.equals(LINKS.facets$vw9T.getName())) { + return facetsAccessor; + } + if (role.equals(LINKS.dependencies$vC8r.getName())) { + return dependenciesAccessor; + } + if (role.equals(LINKS.languageDependencies$vKlY.getName())) { + return languageDependenciesAccessor; + } + return super.getChildAccessor(role); + } + @Override + protected TreeElementAsNode.IPropertyAccessor getPropertyAccessor(String role) { + if (role.equals(PROPS.name$MnvL.getName())) { + return nameAccessor; + } + if (role.equals(PROPS.id$7MjP.getName())) { + return idAccessor; + } + if (role.equals(PROPS.moduleVersion$sDQK.getName())) { + return moduleVersionAccessor; + } + if (role.equals(PROPS.compileInMPS$sEzN.getName())) { + return compileInMPSAccessor; + } + if (role.equals(PROPS.virtualPackage$EkXl.getName())) { + return virtualFolderAccessor; + } + return super.getPropertyAccessor(role); + } + + @Override + protected TreeElementAsNode.IReferenceAccessor getReferenceAccessor(String role) { + return super.getReferenceAccessor(role); + } + + @Override + public INode getParent() { + if (!(SRepositoryAsNode.isVisible(getElement()))) { + return null; + } + return new SRepositoryAsNode(getElement().getRepository()); + } + + @Override + public String getRoleInParent() { + if (!(SRepositoryAsNode.isVisible(getElement()))) { + return null; + } + return ((isTempModule(getElement()) ? LINKS.tempModules$Zqoa : LINKS.modules$jBPn)).getName(); + } + + @NotNull + @Override + public INodeReference getReference() { + return new NodeReference(getElement().getModuleReference()); + } + + @Nullable + public ModuleDependencyAsNode findDependency(SModuleId dependencyId) { + if (!((getElement() instanceof AbstractModule))) { + return null; + } + ModuleDescriptor moduleDescriptor = ((AbstractModule) getElement()).getModuleDescriptor(); + if (moduleDescriptor == null) { + return null; + } + for (IMapping entry : MapSequence.fromMap(moduleDescriptor.getDependencyVersions())) { + if (Objects.equals(entry.key().getModuleId(), dependencyId)) { + return new ModuleDependencyAsNode(entry.key(), entry.value(), isDirectDependency(getElement(), entry.key().getModuleId()), isReexport(getElement(), entry.key().getModuleId()), getElement(), getDependencyScope(getElement(), entry.key().getModuleId())); + } + } + return null; + } + + @Nullable + public SingleLanguageDependencyAsNode findSingleLanguageDependency(SModuleId dependencyId) { + if (!((getElement() instanceof AbstractModule))) { + return null; + } + ModuleDescriptor moduleDescriptor = ((AbstractModule) getElement()).getModuleDescriptor(); + if (moduleDescriptor != null) { + for (IMapping entry : MapSequence.fromMap(moduleDescriptor.getDependencyVersions())) { + if (Objects.equals(entry.key().getModuleId(), dependencyId)) { + return new SingleLanguageDependencyAsNode(entry.key(), entry.value(), getElement()); + } + } + } + return null; + } + @Nullable + public DevKitDependencyAsNode findDevKitDependency(SModuleId dependencyId) { + if (!((getElement() instanceof AbstractModule))) { + return null; + } + ModuleDescriptor moduleDescriptor = ((AbstractModule) getElement()).getModuleDescriptor(); + if (moduleDescriptor != null) { + for (SModuleReference devKit : CollectionSequence.fromCollection(moduleDescriptor.getUsedDevkits())) { + if (Objects.equals(devKit.getModuleId(), dependencyId)) { + return new DevKitDependencyAsNode(devKit, getElement()); + } + } + } + return null; + } + + public static class NodeReference implements INodeReference { + private SModuleReference moduleRef; + + public NodeReference(SModuleReference moduleRef) { + this.moduleRef = moduleRef; + } + + public SModuleReference getModuleRef() { + return this.moduleRef; + } + + @Nullable + @Override + public INode resolveNode(@Nullable IArea area) { + final Wrappers._T repo = new Wrappers._T(null); + if (area != null) { + List areas = area.collectAreas(); + repo.value = ListSequence.fromList(areas).ofType(MPSArea.class).select(new ISelector() { + public SRepository select(MPSArea it) { + return it.getRepository(); + } + }).where(new NotNullWhereFilter()).first(); + } + if (repo.value == null) { + repo.value = MPSModuleRepository.getInstance(); + } + + final Wrappers._T resolved = new Wrappers._T(null); + if (repo.value.getModelAccess().canRead()) { + resolved.value = moduleRef.resolve(repo.value); + } else { + repo.value.getModelAccess().runReadAction(new Runnable() { + public void run() { + resolved.value = moduleRef.resolve(repo.value); + } + }); + } + return (resolved.value == null ? null : new SModuleAsNode(resolved.value)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if ((moduleRef != null ? !(moduleRef.equals(that.moduleRef)) : that.moduleRef != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((moduleRef != null ? ((Object) moduleRef).hashCode() : 0)); + return result; + } + } + private static String check_jbj149_a0a0a0a0b0a0a0f(ModulePath checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getVirtualFolder(); + } + return null; + } + private static int check_jbj149_a0a0b0a0a0h(ModuleDescriptor checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModuleVersion(); + } + return 0; + } + private static boolean check_jbj149_a0a0a0b0a0a0j(ModuleDescriptor checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getCompileInMPS(); + } + return false; + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink models$h3QT = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x69652614fd1c512L, "models"); + /*package*/ static final SContainmentLink facets$vw9T = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde953529916cL, "facets"); + /*package*/ static final SContainmentLink dependencies$vC8r = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299179L, "dependencies"); + /*package*/ static final SContainmentLink languageDependencies$vKlY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299187L, "languageDependencies"); + /*package*/ static final SContainmentLink modules$jBPn = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x69652614fd1c517L, "modules"); + /*package*/ static final SContainmentLink tempModules$Zqoa = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x72291b7f31486ecaL, "tempModules"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$7MjP = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x3aa34013f2a802e0L, "id"); + /*package*/ static final SProperty moduleVersion$sDQK = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299142L, "moduleVersion"); + /*package*/ static final SProperty compileInMPS$sEzN = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299145L, "compileInMPS"); + /*package*/ static final SProperty virtualPackage$EkXl = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x115eca8579fL, "virtualPackage"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeAPI.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeAPI.java new file mode 100644 index 00000000..63b736cf --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeAPI.java @@ -0,0 +1,184 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.modelix.model.api.INode; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.internal.collections.runtime.CollectionSequence; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IMapping; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import org.jetbrains.mps.openapi.model.SReference; +import org.jetbrains.mps.openapi.model.SModel; +import org.modelix.model.api.NodeUtilKt; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; + +public class SNodeAPI { + + public static void clearChildren(SNode parent, SContainmentLink role) { + while (parent.getChildren(role).iterator().hasNext()) { + parent.removeChild(parent.getChildren(role).iterator().next()); + } + } + + public static SNode replaceWithNewChild(SNode parent, SContainmentLink role, SAbstractConcept childConcept) { + clearChildren(parent, role); + return addNewChild(parent, role, 0, childConcept); + } + + public static T replaceWithCopy(T sourceNode, SNode targetParent, SContainmentLink targetRole) { + clearChildren(targetParent, targetRole); + return copyTo(sourceNode, targetParent, targetRole, 0); + } + + public static SNode addNewChild(SNode parent, SContainmentLink role, SAbstractConcept childConcept) { + return addNewChild(parent, role, -1, childConcept); + } + + public static SNode addNewChild(SNode parent, SContainmentLink role) { + return addNewChild(parent, role, -1, role.getTargetConcept()); + } + + public static SNode addNewChild(SNode parent, SContainmentLink role, int index) { + return addNewChild(parent, role, index, role.getTargetConcept()); + } + + public static SNode addNewChild(SNode parent, SContainmentLink role, int index, SAbstractConcept childConcept) { + INode newChild = SNodeToNodeAdapter.wrap(parent).addNewChild(role.getName(), index, SConceptAdapter.wrap(childConcept)); + if (newChild == null) { + throw new RuntimeException("addNewChild has to return the created child node"); + } + return NodeToSNodeAdapter.wrap(newChild); + } + + public static void moveChild(SNode newParent, SContainmentLink newRole, int newIndex, SNode child) { + SNodeToNodeAdapter.wrap(newParent).moveChild(newRole.getName(), newIndex, SNodeToNodeAdapter.wrap(child)); + } + + public static T copyAsMPSNode(T sourceNode) { + return (T) copyRootNode(sourceNode, SConceptOperations.createNewNode(SNodeOperations.asInstanceConcept(SNodeOperations.getConcept(sourceNode)))); + } + + public static T copyTo(T sourceNode, SNode targetParent, SContainmentLink targetRole, int targetIndex) { + SAbstractConcept concept = SNodeOperations.getConcept(sourceNode); + SNode copy = addNewChild(targetParent, targetRole, targetIndex, concept); + return copyRootNode(sourceNode, ((T) copy)); + } + + protected static T copyRootNode(T sourceNode, T copy) { + Map copiedNodes = MapSequence.fromMap(new HashMap()); + MapSequence.fromMap(copiedNodes).put(sourceNode, copy); + copyProperties(sourceNode, copy); + copyChildren(sourceNode, copy, copiedNodes); + resolveReferences(copiedNodes); + return copy; + } + + private static SNode copyTo(SNode sourceNode, SNode targetParent, SContainmentLink targetRole, int targetIndex, Map copiedNodes) { + SConcept concept = sourceNode.getConcept(); + SNode copy = addNewChild(targetParent, targetRole, targetIndex, concept); + MapSequence.fromMap(copiedNodes).put(sourceNode, copy); + copyProperties(sourceNode, copy); + copyChildren(sourceNode, copy, copiedNodes); + return copy; + } + + private static void copyProperties(SNode source, SNode target) { + for (SProperty property : CollectionSequence.fromCollection(source.getConcept().getProperties())) { + String value = source.getProperty(property); + if (value != null) { + target.setProperty(property, value); + } + } + } + + private static void copyChildren(SNode source, SNode target, Map copiedNodes) { + for (SContainmentLink link : CollectionSequence.fromCollection(source.getConcept().getContainmentLinks())) { + for (SNode child : Sequence.fromIterable(source.getChildren(link))) { + copyTo(child, target, link, -1, copiedNodes); + } + } + } + + private static void resolveReferences(Map copiedNodes) { + for (IMapping entry : MapSequence.fromMap(copiedNodes)) { + for (SReferenceLink link : CollectionSequence.fromCollection(entry.key().getConcept().getReferenceLinks())) { + SReference ref = entry.key().getReference(link); + if (ref == null) { + continue; + } + SNode originalTarget = ref.getTargetNode(); + if (originalTarget == null) { + continue; + } + SNode copiedTarget = MapSequence.fromMap(copiedNodes).get(originalTarget); + entry.value().setReferenceTarget(link, (copiedTarget != null ? copiedTarget : originalTarget)); + } + } + } + + public static String uniqueString(SNode node) { + node = NodeToSNodeAdapter.wrap(SNodeToNodeAdapter.wrap(node)); + if (node instanceof jetbrains.mps.smodel.SNode) { + return node.getReference().toString(); + } + throw new RuntimeException("Cannot calculate unique string for " + node); + } + + public static SModel getOriginalModel(SNode node) { + return check_jvh1te_a0a33(getOriginalNode(node)); + } + + public static SNode getOriginalNode(SNode node) { + if (node == null) { + return null; + } + return as_jvh1te_a0b0jb(NodeToSNodeAdapter.wrap(NodeUtilKt.deepUnwrapNode(SNodeToNodeAdapter.wrap(node))), jetbrains.mps.smodel.SNode.class); + } + + public static SNode tryGetUnwrappedNode(SNode node) { + SNode unwrapped = getOriginalNode(node); + return (unwrapped != null ? unwrapped : node); + } + + public static void runRead(SNode snode, final Runnable r) { + SNodeToNodeAdapter.wrap(snode).getArea().executeRead(new Function0() { + public Unit invoke() { + r.run(); + return Unit.INSTANCE; + } + }); + } + + public static void runWrite(SNode snode, final Runnable r) { + SNodeToNodeAdapter.wrap(snode).getArea().executeWrite(new Function0() { + public Unit invoke() { + r.run(); + return Unit.INSTANCE; + } + }); + } + + public static boolean isValid(SNode snode) { + return (snode == null ? true : SNodeToNodeAdapter.wrap(snode).isValid()); + } + private static SModel check_jvh1te_a0a33(SNode checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModel(); + } + return null; + } + private static T as_jvh1te_a0b0jb(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeReferenceAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeReferenceAdapter.java new file mode 100644 index 00000000..c86c37d5 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeReferenceAdapter.java @@ -0,0 +1,55 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.INodeReference; +import org.jetbrains.mps.openapi.model.SNodeReference; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.INode; +import org.modelix.model.area.IArea; + +public class SNodeReferenceAdapter implements INodeReference { + + private SNodeReference ref; + public SNodeReferenceAdapter(@NotNull SNodeReference ref) { + this.ref = ref; + } + + public SNodeReference getReference() { + return ref; + } + + @Nullable + @Override + public INode resolveNode(IArea area) { + return area.resolveNode(this); + } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + SNodeReferenceAdapter that = (SNodeReferenceAdapter) o; + if ((ref != null ? !(ref.equals(that.ref)) : that.ref != null)) { + return false; + } + + return true; + } + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((ref != null ? ((Object) ref).hashCode() : 0)); + return result; + } + + @Override + public String toString() { + return "SNodeReferenceAdapter{" + "ref=" + ref + "}"; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeToNodeAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeToNodeAdapter.java new file mode 100644 index 00000000..5841b62a --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SNodeToNodeAdapter.java @@ -0,0 +1,392 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.INodeEx; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.area.IArea; +import org.modelix.model.api.IConcept; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConceptReference; +import org.modelix.model.api.IChildLink; +import org.modelix.model.api.INodeKt; +import org.modelix.model.api.INodeReference; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import java.util.Objects; +import org.modelix.model.api.ILanguageRepository; +import org.modelix.model.api.IReferenceLink; +import org.modelix.model.area.ContextArea; +import org.jetbrains.mps.openapi.language.SProperty; +import java.util.List; +import org.jetbrains.mps.openapi.model.SReference; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import jetbrains.mps.smodel.adapter.MetaAdapterByDeclaration; +import org.modelix.model.api.IProperty; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class SNodeToNodeAdapter implements INodeEx { + + public static INode wrap(SNode nodeToWrap) { + if (nodeToWrap == null) { + return null; + } + if (nodeToWrap instanceof NodeToSNodeAdapter) { + return ((NodeToSNodeAdapter) nodeToWrap).getWrapped(); + } + return new SNodeToNodeAdapter(nodeToWrap); + } + + public static INode wrap(INode nodeToWrap) { + // Makes code generation easier. wrap can always be applied to ensure a value is an INode. + return nodeToWrap; + } + + private final SNode node; + + private SNodeToNodeAdapter(SNode node1) { + node = node1; + notifyModelContentDependency(); + } + + protected void notifyModelContentDependency() { + SModel model = node.getModel(); + if (model == null) { + return; + } + // TODO + } + + @NotNull + @Override + public IArea getArea() { + return new MPSArea(); + } + + @Override + public boolean isValid() { + return true; + } + + public SNode getWrapped() { + return node; + } + + @Override + public IConcept getConcept() { + SConcept sconcept = node.getConcept(); + IConcept concept = BootstrapConceptMappings.INSTANCE.getConcept(sconcept); + if (concept != null) { + return concept; + } + return new SConceptAdapter(sconcept); + } + + @Nullable + @Override + public IConceptReference getConceptReference() { + return getConcept().getReference(); + } + + @Override + public String getRoleInParent() { + IChildLink link = getContainmentLink(); + if (link == null) { + return null; + } + return INodeKt.key(link, this); + } + + @Override + public INode getParent() { + notifyModelContentDependency(); + SNode parent = node.getParent(); + if (parent != null) { + return wrap(parent); + } + SModel model = node.getModel(); + if (model != null) { + return new SModelAsNode(model); + } + return null; + } + + @Override + public INodeReference getReference() { + return new SNodeReferenceAdapter(node.getReference()); + } + + @Override + public Iterable getChildren(String role) { + notifyModelContentDependency(); + return getChildren(INodeKt.resolveChildLink(this, role)); + } + + @Override + public Iterable getAllChildren() { + notifyModelContentDependency(); + Iterable children = node.getChildren(); + return Sequence.fromIterable(children).select(new ISelector() { + public INode select(SNode it) { + INode n = new SNodeToNodeAdapter(it); + return n; + } + }); + } + + @Override + public void moveChild(String role, int index, INode child) { + IChildLink link = INodeKt.resolveChildLink(this, role); + moveChild(link, index, child); + } + + @Override + public INode addNewChild(final String role, int index, IConcept concept_) { + Iterable links = node.getConcept().getContainmentLinks(); + SContainmentLink link = Sequence.fromIterable(links).findFirst(new IWhereFilter() { + public boolean accept(SContainmentLink it) { + return Objects.equals(it.getName(), role); + } + }); + if (link == null) { + throw new RuntimeException(node.getConcept() + " has no containment link '" + role + "'"); + } + return addNewChild(new SContainmentLinkAdapter(link), index, concept_); + } + + @NotNull + @Override + public INode addNewChild(@Nullable String role, int index, @Nullable IConceptReference conceptRef) { + IConcept concept = (conceptRef == null ? null : ILanguageRepository.Companion.resolveConcept(conceptRef)); + return addNewChild(role, index, concept); + } + + @Override + public void removeChild(INode child) { + node.removeChild(((SNodeToNodeAdapter) child).node); + } + + @Override + public INode getReferenceTarget(String role) { + IReferenceLink link = INodeKt.resolveReferenceLink(this, role); + return getReferenceTarget(link); + } + + @Nullable + @Override + public INodeReference getReferenceTargetRef(@NotNull String role) { + return check_8812ym_a0a14(getReferenceTarget(role), this); + } + + @Override + public void setReferenceTarget(String role, INode target) { + setReferenceTarget(INodeKt.resolveReferenceLink(this, role), target); + } + + @Override + public void setReferenceTarget(@NotNull String role, @Nullable INodeReference target) { + INode targetNode = (target == null ? null : target.resolveNode(ContextArea.INSTANCE.getArea())); + setReferenceTarget(role, targetNode); + } + + @Override + public String getPropertyValue(final String role) { + notifyModelContentDependency(); + Iterable properties = node.getProperties(); + SProperty property = Sequence.fromIterable(properties).findFirst(new IWhereFilter() { + public boolean accept(SProperty it) { + return Objects.equals(it.getName(), role); + } + }); + if (property == null) { + return null; + } + return getPropertyValue(new SPropertyAdapter(property)); + } + + @Override + public void setPropertyValue(String role, String value) { + setPropertyValue(INodeKt.resolveProperty(this, role), value); + } + + @NotNull + @Override + public List getPropertyRoles() { + Iterable properties = node.getProperties(); + return Sequence.fromIterable(properties).select(new ISelector() { + public String select(SProperty it) { + return it.getName(); + } + }).toListSequence(); + } + @NotNull + @Override + public List getReferenceRoles() { + Iterable references = node.getReferences(); + return Sequence.fromIterable(references).select(new ISelector() { + public String select(SReference it) { + return it.getLink().getName(); + } + }).toListSequence(); + } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + SNodeToNodeAdapter that = (SNodeToNodeAdapter) o; + if ((node != null ? !(node.equals(that.node)) : that.node != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((node != null ? ((Object) node).hashCode() : 0)); + return result; + } + + @Override + public String toString() { + return "" + node; + } + + @Override + public boolean usesRoleIds() { + return false; + } + + @NotNull + @Override + public INode addNewChild(@NotNull IChildLink role, int index, @Nullable IConcept concept_) { + SContainmentLink link = ((SContainmentLinkAdapter) role).getLink(); + Iterable children_ = node.getChildren(link); + List children = Sequence.fromIterable(children_).toListSequence(); + if (index > ListSequence.fromList(children).count()) { + throw new IndexOutOfBoundsException(index + " > " + Sequence.fromIterable(children_).count()); + } + SAbstractConcept concept = SConceptAdapter.unwrap(concept_); + if (concept == null) { + concept = link.getTargetConcept(); + } + SConcept instantiatableConcept = MetaAdapterByDeclaration.asInstanceConcept(concept); + SModel model = node.getModel(); + SNode newChild = (model == null ? new jetbrains.mps.smodel.SNode(instantiatableConcept) : model.createNode(instantiatableConcept)); + if (index == -1 || index == ListSequence.fromList(children).count()) { + node.addChild(link, newChild); + } else { + node.insertChildBefore(link, newChild, ListSequence.fromList(children).getElement(index)); + } + return wrap(newChild); + } + @NotNull + @Override + public INode addNewChild(@NotNull IChildLink role, int index, @Nullable IConceptReference conceptRef) { + IConcept concept = (conceptRef == null ? null : ILanguageRepository.Companion.resolveConcept(conceptRef)); + return addNewChild(role, index, concept); + } + @NotNull + @Override + public Iterable getChildren(@NotNull final IChildLink link) { + return Sequence.fromIterable(getAllChildren()).where(new IWhereFilter() { + public boolean accept(INode it) { + return Objects.equals(INodeKt.getContainmentLink(it), link); + } + }); + } + @Nullable + @Override + public IChildLink getContainmentLink() { + SContainmentLink link = null; + + SNode parent = node.getParent(); + if (parent != null) { + link = node.getContainmentLink(); + } else { + SModel model = node.getModel(); + if (model != null) { + link = LINKS.rootNodes$jxXY; + } + } + return (link == null ? null : new SContainmentLinkAdapter(link)); + + } + @Nullable + @Override + public String getPropertyValue(@NotNull IProperty property) { + return node.getProperty(((SPropertyAdapter) property).getProperty()); + } + @Nullable + @Override + public INode getReferenceTarget(@NotNull IReferenceLink link) { + return wrap(node.getReferenceTarget(((SReferenceLinkAdapter) link).getLink())); + } + @Nullable + @Override + public INodeReference getReferenceTargetRef(@NotNull IReferenceLink role) { + return check_8812ym_a0a76(getReferenceTarget(role), this); + } + @Override + public void moveChild(@NotNull IChildLink role, int index, @NotNull INode child) { + SContainmentLink link = ((SContainmentLinkAdapter) role).getLink(); + Iterable children_ = node.getChildren(link); + List children = Sequence.fromIterable(children_).toListSequence(); + if (index > ListSequence.fromList(children).count()) { + throw new IndexOutOfBoundsException(index + " > " + Sequence.fromIterable(children_).count()); + } + SNode schild = NodeToSNodeAdapter.wrap(child); + if (SNodeOperations.getParent(schild) != null) { + SNodeOperations.deleteNode(schild); + } + if (index == -1 || index == ListSequence.fromList(children).count()) { + node.addChild(link, schild); + } else { + node.insertChildBefore(link, schild, ListSequence.fromList(children).getElement(index)); + } + } + @Override + public void setPropertyValue(@NotNull IProperty property, @Nullable String value) { + node.setProperty(((SPropertyAdapter) property).getProperty(), value); + } + @Override + public void setReferenceTarget(@NotNull IReferenceLink link, @Nullable INode target) { + SNode snodeTarget = NodeToSNodeAdapter.wrap(target); + node.setReferenceTarget(((SReferenceLinkAdapter) link).getLink(), snodeTarget); + } + @Override + public void setReferenceTarget(@NotNull IReferenceLink role, @Nullable INodeReference target) { + INode targetNode = (target == null ? null : target.resolveNode(ContextArea.INSTANCE.getArea())); + setReferenceTarget(role, targetNode); + } + private static INodeReference check_8812ym_a0a14(INode checkedDotOperand, SNodeToNodeAdapter checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getReference(); + } + return null; + } + private static INodeReference check_8812ym_a0a76(INode checkedDotOperand, SNodeToNodeAdapter checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getReference(); + } + return null; + } + + private static final class LINKS { + /*package*/ static final SContainmentLink rootNodes$jxXY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x69652614fd1c514L, "rootNodes"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SPropertyAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SPropertyAdapter.java new file mode 100644 index 00000000..edebdcd6 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SPropertyAdapter.java @@ -0,0 +1,67 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.IProperty; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.smodel.adapter.ids.MetaIdHelper; +import org.modelix.model.api.IConcept; + +public class SPropertyAdapter implements IProperty { + + private SProperty property; + + public SPropertyAdapter(SProperty property1) { + property = property1; + } + + @NotNull + @Override + public String getUID() { + return MetaIdHelper.getProperty(property).serialize(); + } + + @NotNull + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(property.getOwner()); + } + + public SProperty getProperty() { + return property; + } + + @NotNull + @Override + public String getSimpleName() { + return property.getName(); + } + + @Override + public boolean isOptional() { + return true; + } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + SPropertyAdapter that = (SPropertyAdapter) o; + if ((property != null ? !(property.equals(that.property)) : that.property != null)) { + return false; + } + + return true; + } + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((property != null ? ((Object) property).hashCode() : 0)); + return result; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SReferenceLinkAdapter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SReferenceLinkAdapter.java new file mode 100644 index 00000000..770ee398 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SReferenceLinkAdapter.java @@ -0,0 +1,73 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.IReferenceLink; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.smodel.adapter.ids.MetaIdHelper; +import org.modelix.model.api.IConcept; + +public class SReferenceLinkAdapter implements IReferenceLink { + + private SReferenceLink link; + + public SReferenceLinkAdapter(SReferenceLink link1) { + link = link1; + } + + public SReferenceLink getLink() { + return link; + } + + @NotNull + @Override + public String getUID() { + return MetaIdHelper.getAssociation(link).serialize(); + } + + @NotNull + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(link.getOwner()); + } + + @NotNull + @Override + public String getSimpleName() { + return link.getName(); + } + + @NotNull + @Override + public IConcept getTargetConcept() { + return new SConceptAdapter(link.getTargetConcept()); + } + + @Override + public boolean isOptional() { + return link.isOptional(); + } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + SReferenceLinkAdapter that = (SReferenceLinkAdapter) o; + if ((link != null ? !(link.equals(that.link)) : that.link != null)) { + return false; + } + + return true; + } + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((link != null ? ((Object) link).hashCode() : 0)); + return result; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SRepositoryAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SRepositoryAsNode.java new file mode 100644 index 00000000..e00aea43 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SRepositoryAsNode.java @@ -0,0 +1,168 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.module.SRepository; +import org.jetbrains.mps.openapi.module.SModule; +import org.modelix.model.api.INode; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import jetbrains.mps.internal.collections.runtime.ISelector; +import java.util.List; +import jetbrains.mps.project.Project; +import jetbrains.mps.project.ProjectManager; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.project.MPSProject; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.area.IArea; +import org.modelix.model.api.IConcept; +import org.modelix.model.api.INodeReference; +import org.jetbrains.annotations.Nullable; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; + +public class SRepositoryAsNode extends TreeElementAsNode { + + public static boolean isVisible(SModule module) { + return true; + } + + private static TreeElementAsNode.IChildAccessor modulesAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(SRepository repository) { + Iterable modules = repository.getModules(); + return Sequence.fromIterable(modules).where(new IWhereFilter() { + public boolean accept(SModule it) { + return isVisible(it); + } + }).where(new IWhereFilter() { + public boolean accept(SModule it) { + return !(SModuleAsNode.isTempModule(it)); + } + }).select(new ISelector() { + public SModuleAsNode select(SModule it) { + return new SModuleAsNode(it); + } + }); + } + }; + private static TreeElementAsNode.IChildAccessor tempModulesAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(SRepository repository) { + Iterable modules = repository.getModules(); + return Sequence.fromIterable(modules).where(new IWhereFilter() { + public boolean accept(SModule it) { + return isVisible(it); + } + }).where(new IWhereFilter() { + public boolean accept(SModule it) { + return SModuleAsNode.isTempModule(it); + } + }).select(new ISelector() { + public SModuleAsNode select(SModule it) { + return new SModuleAsNode(it); + } + }); + } + }; + private static TreeElementAsNode.IChildAccessor projectsAccessor = new TreeElementAsNode.IChildAccessor() { + public Iterable get(SRepository repository) { + List projects = ProjectManager.getInstance().getOpenedProjects(); + return ListSequence.fromList(projects).ofType(MPSProject.class).select(new ISelector() { + public ProjectAsNode select(MPSProject it) { + return new ProjectAsNode(it); + } + }); + } + }; + + public SRepositoryAsNode(SRepository repository) { + super(repository); + } + + @NotNull + @Override + public IArea getArea() { + return new MPSArea(getElement()); + } + + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.Repository$db); + } + + @Override + protected TreeElementAsNode.IChildAccessor getChildAccessor(String role) { + if (role.equals(LINKS.modules$jBPn.getName())) { + return modulesAccessor; + } + if (role.equals(LINKS.tempModules$Zqoa.getName())) { + return tempModulesAccessor; + } + if (role.equals(LINKS.projects$NW07.getName())) { + return projectsAccessor; + } + return super.getChildAccessor(role); + } + @Override + protected TreeElementAsNode.IPropertyAccessor getPropertyAccessor(String role) { + return super.getPropertyAccessor(role); + } + @Override + protected TreeElementAsNode.IReferenceAccessor getReferenceAccessor(String role) { + return super.getReferenceAccessor(role); + } + @Override + public INode getParent() { + return null; + } + @Override + public String getRoleInParent() { + return null; + } + @Override + public String toString() { + return "repository"; + } + + @NotNull + @Override + public INodeReference getReference() { + return NodeReference.INSTANCE; + } + + public static class NodeReference implements INodeReference { + public static NodeReference INSTANCE = new NodeReference(); + private NodeReference() { + } + + @Nullable + @Override + public INode resolveNode(@Nullable IArea area) { + SRepository repo = null; + if (area != null) { + List areas = area.collectAreas(); + repo = ListSequence.fromList(areas).ofType(MPSArea.class).select(new ISelector() { + public SRepository select(MPSArea it) { + return it.getRepository(); + } + }).where(new NotNullWhereFilter()).first(); + } + if (repo == null) { + repo = MPSModuleRepository.getInstance(); + } + return new SRepositoryAsNode(repo); + } + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Repository$db = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, "org.modelix.model.repositoryconcepts.structure.Repository"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink modules$jBPn = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x69652614fd1c517L, "modules"); + /*package*/ static final SContainmentLink tempModules$Zqoa = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x72291b7f31486ecaL, "tempModules"); + /*package*/ static final SContainmentLink projects$NW07 = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x620a8558361d3e0cL, "projects"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SingleLanguageDependencyAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SingleLanguageDependencyAsNode.java new file mode 100644 index 00000000..6916de20 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/SingleLanguageDependencyAsNode.java @@ -0,0 +1,329 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.module.SModuleReference; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConceptReference; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.area.IArea; +import org.modelix.model.api.INodeReference; +import org.modelix.model.api.IConcept; +import jetbrains.mps.internal.collections.runtime.LinkedListSequence; +import java.util.LinkedList; +import java.util.Collections; +import org.modelix.model.api.IChildLink; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import java.util.Objects; +import java.util.List; +import org.modelix.model.api.IProperty; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.modelix.model.api.IReferenceLink; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.mps.openapi.module.SModuleId; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SProperty; + +public class SingleLanguageDependencyAsNode implements INode { + private SModuleReference moduleReference; + private int languageVersion; + private SModule moduleImporter; + private SModel modelImporter; + + public SingleLanguageDependencyAsNode(SModuleReference moduleReference, int languageVersion, SModule importer) { + this.moduleReference = moduleReference; + this.languageVersion = languageVersion; + this.moduleImporter = importer; + } + + public SingleLanguageDependencyAsNode(SModuleReference moduleReference, int languageVersion, SModel importer) { + this.moduleReference = moduleReference; + this.languageVersion = languageVersion; + this.modelImporter = importer; + } + + @Nullable + @Override + public IConceptReference getConceptReference() { + return getConcept().getReference(); + } + + public SModuleReference getModuleReference() { + return this.moduleReference; + } + public int getLanguageVersion() { + return this.languageVersion; + } + + @NotNull + @Override + public IArea getArea() { + return new MPSArea(); + } + + @Override + public boolean isValid() { + return true; + } + + @NotNull + @Override + public INodeReference getReference() { + if (this.moduleImporter != null) { + return new NodeReference(this.moduleImporter.getModuleReference(), this.moduleReference.getModuleId()); + } + if (this.modelImporter != null) { + return new NodeReference(this.modelImporter.getReference(), this.moduleReference.getModuleId()); + } + throw new IllegalStateException(); + } + + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.SingleLanguageDependency$_9); + } + + @Nullable + @Override + public String getRoleInParent() { + if (this.moduleImporter != null) { + return LINKS.languageDependencies$vKlY.getName(); + } + if (this.modelImporter != null) { + return LINKS.usedLanguages$QK4E.getName(); + } + throw new IllegalStateException(); + } + + @Nullable + @Override + public INode getParent() { + if (this.moduleImporter != null) { + SModuleAsNode.wrap(this.moduleImporter); + } + if (this.modelImporter != null) { + SModelAsNode.wrap(this.modelImporter); + } + throw new IllegalStateException(); + } + + @NotNull + @Override + public Iterable getChildren(@Nullable String role) { + return LinkedListSequence.fromLinkedListNew(new LinkedList()); + } + + @NotNull + @Override + public Iterable getAllChildren() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + Iterable links = concept.getAllChildLinks(); + return Sequence.fromIterable(links).select(new ISelector>() { + public Iterable select(IChildLink it) { + return getChildren(it.getName()); + } + }).translate(new ITranslator2, INode>() { + public Iterable translate(Iterable it) { + return it; + } + }); + } + + @Override + public void moveChild(@Nullable String string, int i, @NotNull INode node) { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public INode addNewChild(@Nullable String string, int i, @Nullable IConcept concept) { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public INode addNewChild(@Nullable String string, int i, @Nullable IConceptReference reference) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeChild(@NotNull INode node) { + throw new UnsupportedOperationException(); + } + + @Nullable + @Override + public INode getReferenceTarget(@NotNull String role) { + return null; + } + + @Nullable + @Override + public INodeReference getReferenceTargetRef(@NotNull String string) { + return null; + } + + @Override + public void setReferenceTarget(@NotNull String string, @Nullable INode node) { + throw new UnsupportedOperationException(); + } + + @Override + public void setReferenceTarget(@NotNull String string, @Nullable INodeReference reference) { + throw new UnsupportedOperationException(); + } + + @Nullable + @Override + public String getPropertyValue(@NotNull String propertyName) { + if (Objects.equals(PROPS.version$ApUL.getName(), propertyName)) { + return Integer.toString(this.languageVersion); + } else if (Objects.equals(PROPS.name$lpYq.getName(), propertyName)) { + return this.moduleReference.getModuleName(); + } else if (Objects.equals(PROPS.uuid$lpJp.getName(), propertyName)) { + return this.moduleReference.getModuleId().toString(); + } else { + return null; + } + } + @Override + public void setPropertyValue(@NotNull String string, @Nullable String string1) { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public List getPropertyRoles() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + List allProperties = concept.getAllProperties(); + return ListSequence.fromList(allProperties).select(new ISelector() { + public String select(IProperty it) { + return it.getName(); + } + }).toListSequence(); + } + + @NotNull + @Override + public List getReferenceRoles() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + List allReferenceLinks = concept.getAllReferenceLinks(); + return ListSequence.fromList(allReferenceLinks).select(new ISelector() { + public String select(IReferenceLink it) { + return it.getName(); + } + }).toListSequence(); + } + + public static class NodeReference implements INodeReference { + private SModuleReference userModuleReference; + private SModelReference userModel; + private SModuleId usedModuleId; + + public NodeReference(SModuleReference userModuleReference, SModuleId usedModuleId) { + this.userModuleReference = userModuleReference; + this.usedModuleId = usedModuleId; + } + + public NodeReference(SModelReference userModel, SModuleId usedModuleId) { + this.userModel = userModel; + this.usedModuleId = usedModuleId; + } + + @Nullable + @Override + public INode resolveNode(@Nullable IArea area) { + SRepository repo = null; + if (area != null) { + List areas = area.collectAreas(); + repo = ListSequence.fromList(areas).ofType(MPSArea.class).select(new ISelector() { + public SRepository select(MPSArea it) { + return it.getRepository(); + } + }).where(new NotNullWhereFilter()).first(); + } + if (repo == null) { + repo = MPSModuleRepository.getInstance(); + } + + if (this.userModuleReference != null) { + SModule user = userModuleReference.resolve(repo); + if (user == null) { + return null; + } + + return new SModuleAsNode(user).findSingleLanguageDependency(this.usedModuleId); + } else if (this.userModel != null) { + SModel model = userModel.resolve(repo); + return new SModelAsNode(model).findSingleLanguageDependency(this.usedModuleId); + } else { + throw new IllegalStateException(); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + NodeReference that = (NodeReference) o; + if (Objects.equals(this.userModuleReference, that.userModuleReference)) { + return false; + } + if (Objects.equals(this.userModel, that.userModel)) { + return false; + } + if (Objects.equals(this.usedModuleId, that.usedModuleId)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((userModuleReference != null ? ((Object) userModuleReference).hashCode() : 0)); + result = 11 * result + ((usedModuleId != null ? ((Object) usedModuleId).hashCode() : 0)); + result = 37 * result + ((userModel != null ? ((Object) userModel).hashCode() : 0)); + return result; + } + } + + private static final class CONCEPTS { + /*package*/ static final SConcept SingleLanguageDependency$_9 = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529917dL, "org.modelix.model.repositoryconcepts.structure.SingleLanguageDependency"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink languageDependencies$vKlY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299187L, "languageDependencies"); + /*package*/ static final SContainmentLink usedLanguages$QK4E = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x4aaf28cf2092e98eL, "usedLanguages"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$lpYq = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x7c527144386aca0fL, 0x7c527144386aca13L, "name"); + /*package*/ static final SProperty uuid$lpJp = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x7c527144386aca0fL, 0x7c527144386aca12L, "uuid"); + /*package*/ static final SProperty version$ApUL = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529917dL, 0x1e9fde9535299183L, "version"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/TreeElementAsNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/TreeElementAsNode.java new file mode 100644 index 00000000..711e0075 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/TreeElementAsNode.java @@ -0,0 +1,278 @@ +package org.modelix.model.mpsadapters.mps; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import jetbrains.mps.internal.collections.runtime.Sequence; +import java.util.Collections; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConceptReference; +import org.modelix.model.api.IConcept; +import org.modelix.model.area.IArea; +import org.modelix.model.api.ILanguageRepository; +import org.modelix.model.api.IChildLink; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import org.modelix.model.api.INodeReference; +import java.util.List; +import org.modelix.model.api.IProperty; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.modelix.model.api.IReferenceLink; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; + +public abstract class TreeElementAsNode implements INode { + + protected static IPropertyAccessor dummyPropertyAccessor = new IPropertyAccessor() { + public String get(Object element) { + return null; + } + public String set(Object element, String value) { + throw new UnsupportedOperationException(); + } + }; + protected static IChildAccessor dummyChildAccessor = new IChildAccessor() { + public Iterable get(Object element) { + return Sequence.fromIterable(Collections.emptyList()); + } + }; + + private final E element; + + public TreeElementAsNode(@NotNull E element1) { + element = element1; + } + + @Nullable + @Override + public IConceptReference getConceptReference() { + return check_bnhhyh_a0a8(getConcept(), this); + } + + @NotNull + @Override + public abstract IConcept getConcept(); + + @NotNull + @Override + public IArea getArea() { + return new MPSArea(); + } + + @Override + public boolean isValid() { + return true; + } + + protected IPropertyAccessor getPropertyAccessor(String role) { + if (role.equals(PROPS.shortDescription$Yd4v.getName())) { + return dummyPropertyAccessor; + } + if (role.equals(PROPS.virtualPackage$EkXl.getName())) { + return dummyPropertyAccessor; + } + return null; + } + + protected IChildAccessor getChildAccessor(String role) { + if (role.equals(LINKS.smodelAttribute$KJ43.getName())) { + return dummyChildAccessor; + } + return null; + } + protected IReferenceAccessor getReferenceAccessor(String role) { + return null; + } + + public E getElement() { + return element; + } + + @Override + public void moveChild(String role, int index, INode node) { + throw new UnsupportedOperationException(); + } + @Override + public INode addNewChild(String role, int index, @Nullable IConcept concept) { + IChildAccessor accessor = getChildAccessor(role); + if (accessor == null) { + throw new RuntimeException("No accessor defined for child '" + role + "' in " + this.getClass().getCanonicalName()); + } + return accessor.add(element, role, index, concept); + } + @NotNull + @Override + public INode addNewChild(@Nullable String role, int index, @Nullable IConceptReference conceptRef) { + IConcept concept = (conceptRef == null ? null : ILanguageRepository.Companion.resolveConcept(conceptRef)); + return addNewChild(role, index, concept); + } + @Override + public void removeChild(INode child) { + String role = child.getRoleInParent(); + IChildAccessor accessor = getChildAccessor(role); + if (accessor == null) { + throw new RuntimeException("No accessor defined for child '" + role + "' in " + this.getClass().getCanonicalName()); + } + accessor.remove(element, child); + } + @Override + public Iterable getAllChildren() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + Iterable links = concept.getAllChildLinks(); + return Sequence.fromIterable(links).select(new ISelector>() { + public IChildAccessor select(IChildLink it) { + return getChildAccessor(it.getName()); + } + }).translate(new ITranslator2, INode>() { + public Iterable translate(IChildAccessor it) { + return it.get(element); + } + }); + } + @Override + public Iterable getChildren(String role) { + IChildAccessor accessor = getChildAccessor(role); + if (accessor == null) { + throw new RuntimeException("No accessor defined for child '" + role + "' in " + this.getClass().getCanonicalName()); + } + return accessor.get(element); + } + @Override + public String getPropertyValue(String role) { + IPropertyAccessor accessor = getPropertyAccessor(role); + if (accessor == null) { + throw new RuntimeException("No accessor defined for property '" + role + "'"); + } + return accessor.get(element); + } + @Override + public INode getReferenceTarget(String role) { + IReferenceAccessor accessor = getReferenceAccessor(role); + if (accessor == null) { + throw new RuntimeException("No accessor defined for reference '" + role + "'"); + } + return accessor.get(element); + } + @Nullable + @Override + public INodeReference getReferenceTargetRef(@NotNull String role) { + return check_bnhhyh_a0a13(getReferenceTarget(role), this); + } + + @Override + public void setPropertyValue(String role, String value) { + IPropertyAccessor accessor = getPropertyAccessor(role); + if (accessor == null) { + throw new RuntimeException("No accessor defined for property '" + role + "'"); + } + accessor.set(element, value); + } + @Override + public void setReferenceTarget(String role, INode target) { + throw new UnsupportedOperationException(); + } + @Override + public void setReferenceTarget(@NotNull String role, @Nullable INodeReference target) { + throw new UnsupportedOperationException(); + } + @NotNull + @Override + public List getPropertyRoles() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + List allProperties = concept.getAllProperties(); + return ListSequence.fromList(allProperties).select(new ISelector() { + public String select(IProperty it) { + return it.getName(); + } + }).toListSequence(); + } + @NotNull + @Override + public List getReferenceRoles() { + IConcept concept = getConcept(); + if (concept == null) { + return Collections.emptyList(); + } + List allReferenceLinks = concept.getAllReferenceLinks(); + return ListSequence.fromList(allReferenceLinks).select(new ISelector() { + public String select(IReferenceLink it) { + return it.getName(); + } + }).toListSequence(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + TreeElementAsNode that = (TreeElementAsNode) o; + if ((element != null ? !(((Object) element).equals(that.element)) : that.element != null)) { + return false; + } + + return true; + } + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((element != null ? ((Object) element).hashCode() : 0)); + return result; + } + + public interface IPropertyAccessor { + String get(E element); + String set(E element, String value); + } + public interface IChildAccessor { + Iterable get(E element); + default INode add(E element, String role, int index, @Nullable IConcept concept) { + throw new UnsupportedOperationException("Cannot add child in role " + role); + } + default void remove(E element, INode childToRemove) { + throw new UnsupportedOperationException("Cannot remove child " + childToRemove); + } + } + public interface IReferenceAccessor { + INode get(E element); + INode set(E element, INode target); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + element + "]"; + } + private static IConceptReference check_bnhhyh_a0a8(IConcept checkedDotOperand, TreeElementAsNode checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getReference(); + } + return null; + } + private static INodeReference check_bnhhyh_a0a13(INode checkedDotOperand, TreeElementAsNode checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getReference(); + } + return null; + } + + private static final class PROPS { + /*package*/ static final SProperty shortDescription$Yd4v = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x10d34f97574L, "shortDescription"); + /*package*/ static final SProperty virtualPackage$EkXl = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x115eca8579fL, "virtualPackage"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink smodelAttribute$KJ43 = MetaAdapterFactory.getContainmentLink(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x47bf8397520e5942L, "smodelAttribute"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/trace.info b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/trace.info new file mode 100644 index 00000000..d3c2b3d0 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/mps/trace.info @@ -0,0 +1,6719 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/ApplicationPlugin_AppPluginPart.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/ApplicationPlugin_AppPluginPart.java new file mode 100644 index 00000000..4120849f --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/ApplicationPlugin_AppPluginPart.java @@ -0,0 +1,23 @@ +package org.modelix.model.mpsadapters.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.part.ApplicationPluginPart; +import org.modelix.model.api.ILanguageRepository; +import org.modelix.model.mpsadapters.mps.MPSLanguageRepository; +import org.modelix.model.api.INodeReferenceSerializer; + +public class ApplicationPlugin_AppPluginPart extends ApplicationPluginPart { + public ApplicationPlugin_AppPluginPart() { + } + @Override + public void init() { + ILanguageRepository.Companion.register(MPSLanguageRepository.INSTANCE); + INodeReferenceSerializer.Companion.register(MPSNodeReferenceSerializer.INSTANCE); + } + @Override + public void dispose() { + ILanguageRepository.Companion.unregister(MPSLanguageRepository.INSTANCE); + INodeReferenceSerializer.Companion.unregister(MPSNodeReferenceSerializer.INSTANCE); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/MPSNodeReferenceSerializer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/MPSNodeReferenceSerializer.java new file mode 100644 index 00000000..fd97a640 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/MPSNodeReferenceSerializer.java @@ -0,0 +1,78 @@ +package org.modelix.model.mpsadapters.plugin; + +/*Generated by MPS */ + +import org.modelix.model.api.INodeReferenceSerializer; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.api.INodeReference; +import org.modelix.model.mpsadapters.mps.SNodeReferenceAdapter; +import jetbrains.mps.smodel.SNodePointer; +import org.modelix.model.mpsadapters.mps.SModelAsNode; +import org.jetbrains.mps.openapi.persistence.PersistenceFacade; +import org.modelix.model.mpsadapters.mps.SModuleAsNode; +import org.modelix.model.mpsadapters.mps.SRepositoryAsNode; +import java.util.Objects; +import jetbrains.mps.smodel.MPSModuleRepository; +import jetbrains.mps.smodel.adapter.structure.FormatException; +import org.apache.log4j.Level; + +public class MPSNodeReferenceSerializer implements INodeReferenceSerializer { + private static final Logger LOG = LogManager.getLogger(MPSNodeReferenceSerializer.class); + private static final String NODE_PREFIX = "mps-node:"; + private static final String MODEL_PREFIX = "mps-model:"; + private static final String MODULE_PREFIX = "mps-module:"; + private static final String SERIALIZED_GLOBAL_REPOSITORY = "mps-repository"; + + public static final MPSNodeReferenceSerializer INSTANCE = new MPSNodeReferenceSerializer(); + + @Nullable + @Override + public String serialize(@NotNull INodeReference ref) { + if (ref instanceof SNodeReferenceAdapter) { + return NODE_PREFIX + SNodePointer.serialize(((SNodeReferenceAdapter) ref).getReference()); + } else if (ref instanceof SModelAsNode.NodeReference) { + return MODEL_PREFIX + PersistenceFacade.getInstance().asString(((SModelAsNode.NodeReference) ref).getModelRef()); + } else if (ref instanceof SModuleAsNode.NodeReference) { + return MODULE_PREFIX + PersistenceFacade.getInstance().asString(((SModuleAsNode.NodeReference) ref).getModuleRef()); + } else if (ref instanceof SRepositoryAsNode.NodeReference) { + return SERIALIZED_GLOBAL_REPOSITORY; + } else { + return null; + } + } + + @Nullable + @Override + public INodeReference deserialize(@NotNull String serialized) { + if (serialized.startsWith(NODE_PREFIX)) { + return new SNodeReferenceAdapter(PersistenceFacade.getInstance().createNodeReference(serialized.substring(NODE_PREFIX.length()))); + } else if (serialized.startsWith(MODEL_PREFIX)) { + return new SModelAsNode.NodeReference(PersistenceFacade.getInstance().createModelReference(serialized.substring(MODEL_PREFIX.length()))); + } else if (serialized.startsWith(MODULE_PREFIX)) { + return new SModuleAsNode.NodeReference(PersistenceFacade.getInstance().createModuleReference(serialized.substring(MODULE_PREFIX.length()))); + } else if (Objects.equals(serialized, SERIALIZED_GLOBAL_REPOSITORY)) { + return new SRepositoryAsNode(MPSModuleRepository.getInstance()).getReference(); + } + + // legacy deserializer for existing serialized node references without prefix + try { + return new SNodeReferenceAdapter(SNodePointer.deserialize(serialized)); + } catch (FormatException ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to deserialize " + serialized, ex); + } + return null; + } catch (PersistenceFacade.IncorrectNodeIdFormatException ex) { + return null; + } catch (RuntimeException ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to deserialize " + serialized, ex); + } + return null; + } + } + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/Mpsadapters_ApplicationPlugin.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/Mpsadapters_ApplicationPlugin.java new file mode 100644 index 00000000..2054ca73 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/Mpsadapters_ApplicationPlugin.java @@ -0,0 +1,26 @@ +package org.modelix.model.mpsadapters.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.applicationplugins.BaseApplicationPlugin; +import com.intellij.openapi.extensions.PluginId; +import org.jetbrains.annotations.NotNull; +import java.util.List; +import jetbrains.mps.plugins.part.ApplicationPluginPart; + +public class Mpsadapters_ApplicationPlugin extends BaseApplicationPlugin { + private final PluginId myId = PluginId.getId("org.modelix.model.mpsadapters"); + + public Mpsadapters_ApplicationPlugin() { + } + + @NotNull + public PluginId getId() { + return myId; + } + + @Override + public void fillCustomParts(List parts) { + parts.add(new ApplicationPlugin_AppPluginPart()); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/trace.info b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/trace.info new file mode 100644 index 00000000..1a9c7736 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsadapters/plugin/trace.info @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/Binding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/Binding.java new file mode 100644 index 00000000..1d43be25 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/Binding.java @@ -0,0 +1,348 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import java.util.Set; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.LinkedHashSet; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; +import java.util.HashSet; +import java.util.Collections; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import org.modelix.model.api.IBranch; +import org.modelix.model.api.ITreeChangeVisitor; +import org.modelix.model.api.ITree; +import org.modelix.model.api.IWriteTransaction; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import org.apache.log4j.Level; + +public abstract class Binding { + private static final Logger LOG = LogManager.getLogger(Binding.class); + private Binding owner; + private Set ownedBindings = SetSequence.fromSet(new LinkedHashSet()); + private boolean isActive = false; + private List listeners = ListSequence.fromList(new ArrayList()); + @Nullable + protected SyncDirection initialSyncDirection; + @Nullable + protected SyncTask lastTask; + @Nullable + public SyncTask runningTask; + + public Binding(@Nullable SyncDirection initialSyncDirection) { + this.initialSyncDirection = initialSyncDirection; + } + + protected void assertSyncThread() { + getRootBinding().getSyncQueue().assertSyncThread(); + } + + public int getDepth() { + return (owner == null ? 0 : owner.getDepth() + 1); + } + + public SyncTask getPendingTask() { + return this.lastTask; + } + + public SyncTask createTask(@NotNull SyncDirection direction, boolean initial) { + switch (direction) { + case TO_CLOUD: + return new SyncTask(this, direction, initial, SetSequence.fromSetAndArray(new HashSet(), ELockType.MPS_READ, ELockType.CLOUD_WRITE), new Runnable() { + public void run() { + syncToCloud(); + } + }); + case TO_MPS: + // Even if the ITree is passed to the sync method we still need a read transaction on the cloud model + // ITree.getReferenceTarget(...).resolveNode(...) requires a read transaction + return new SyncTask(this, direction, initial, SetSequence.fromSetAndArray(new HashSet(), ELockType.MPS_COMMAND, ELockType.CLOUD_READ), new Runnable() { + public void run() { + syncToMPS(getBranch().getTransaction().getTree()); + } + }); + default: + throw new RuntimeException("Unknown direction: " + direction); + } + } + + public SyncTask createTask(@NotNull SyncDirection direction, boolean initial, Runnable callback) { + SyncTask task = createTask(direction, initial); + task.whenDone(callback); + return task; + } + + public synchronized Set getRequiredSyncLocks(SyncDirection direction) { + if (direction == null) { + return Collections.emptySet(); + } else { + switch (direction) { + case TO_CLOUD: + return SetSequence.fromSetAndArray(new HashSet(), ELockType.MPS_READ, ELockType.CLOUD_WRITE); + case TO_MPS: + // Even if the ITree is passed to the sync method we still need a read transaction on the cloud model + // ITree.getReferenceTarget(...).resolveNode(...) requires a read transaction + return SetSequence.fromSetAndArray(new HashSet(), ELockType.MPS_COMMAND, ELockType.CLOUD_READ); + default: + throw new RuntimeException("Unknown direction: " + direction); + } + } + } + + public void enqueueSync(@NotNull SyncDirection direction, boolean initial, @Nullable Runnable callback) { + if (isSynchronizing()) { + return; + } + forceEnqueueSyncTo(direction, initial, callback); + } + + public void forceEnqueueSyncTo(@NotNull SyncDirection direction, boolean initial, @Nullable Runnable callback) { + SyncTask task = createTask(direction, initial, callback); + boolean isEnqueued = getRootBinding().getSyncQueue().enqueue(task); + if (isEnqueued) { + lastTask = task; + } + } + + public boolean isDone() { + return (lastTask == null || lastTask.isDone()) && Sequence.fromIterable(getOwnedBindings()).all(new IWhereFilter() { + public boolean accept(Binding it) { + return it.isDone(); + } + }); + } + + public IBranch getBranch() { + if (owner != null) { + return owner.getBranch(); + } + return null; + } + + /** + * It's more efficient to diff the tree only once and notify all bindings together about changes instead of calling + * ITree.visitChanges in each binding. + * First the visitor is notified about changes and then syncToMPS is called. The binding has to remember which model + * elements are dirty. + */ + @Nullable + protected abstract ITreeChangeVisitor getTreeChangeVisitor(ITree oldTree, ITree newTree); + + public boolean isActive() { + return isActive; + } + + protected void checkActive() throws IllegalStateException { + if (!(isActive)) { + throw new IllegalStateException("Activate the binding first: " + this); + } + } + + public boolean isSynchronizing() { + return check_cvbvhu_a0a63(runningTask); + } + + public final void syncToMPS(@NotNull ITree tree) { + assertSyncThread(); + checkActive(); + doSyncToMPS(tree); + } + + protected abstract void doSyncToMPS(@NotNull ITree tree); + + public final void syncToCloud() { + assertSyncThread(); + checkActive(); + syncToCloud(getBranch().getWriteTransaction()); + } + + public final void syncToCloud(IWriteTransaction t) { + assertSyncThread(); + checkActive(); + doSyncToCloud(t); + } + + public abstract void doSyncToCloud(IWriteTransaction t); + + public ICloudRepository getCloudRepository() { + if (owner == null) { + return null; + } else { + return owner.getCloudRepository(); + } + } + + public void setOwner(@Nullable final Binding newOwner) { + if (this.owner == newOwner) { + return; + } + if (isActive) { + deactivate(null); + } + if (newOwner == this) { + throw new IllegalArgumentException("Binding can't own itself"); + } + if (newOwner != null && Sequence.fromIterable(newOwner.getOwners()).contains(this)) { + throw new IllegalArgumentException("Binding would be an indirect owner of itself"); + } + if (this.owner != null) { + SetSequence.fromSet(this.owner.ownedBindings).removeElement(this); + this.owner.notifyListeners(new _FunctionTypes._void_P1_E0() { + public void invoke(IListener l) { + l.bindingRemoved(Binding.this); + } + }); + } + this.owner = newOwner; + if (newOwner != null) { + SetSequence.fromSet(newOwner.ownedBindings).addElement(this); + if (newOwner.isActive()) { + this.activate(null); + } + newOwner.notifyListeners(new _FunctionTypes._void_P1_E0() { + public void invoke(IListener l) { + l.bindingAdded(Binding.this); + } + }); + } + this.notifyListeners(new _FunctionTypes._void_P1_E0() { + public void invoke(IListener l) { + l.ownerChanged(newOwner); + } + }); + } + + public Binding getOwner() { + return owner; + } + + public Iterable getOwnedBindings() { + return ownedBindings; + } + + public Iterable getOwners() { + return (owner == null ? Sequence.fromIterable(Collections.emptyList()) : Sequence.fromIterable(Sequence.singleton(owner)).concat(Sequence.fromIterable(owner.getOwners()))); + } + + public Binding getRootOwnerOrSelf() { + return (owner == null ? this : owner.getRootOwnerOrSelf()); + } + + public RootBinding getRootBinding() { + RootBinding root = as_cvbvhu_a0a0a16(getRootOwnerOrSelf(), RootBinding.class); + if (root == null) { + throw new IllegalStateException("Not attached: " + this); + } + return root; + } + + public Iterable getAllBindings() { + return Sequence.fromIterable(Sequence.singleton(this)).concat(SetSequence.fromSet(ownedBindings).translate(new ITranslator2() { + public Iterable translate(Binding it) { + return it.getAllBindings(); + } + })); + } + + public final synchronized void activate(@Nullable Runnable callback) { + if (!(getRootOwnerOrSelf() instanceof RootBinding)) { + throw new IllegalStateException("Set an owner first: " + this); + } + if (isActive) { + return; + } + if (!(this instanceof RootBinding) && !(owner.isActive())) { + throw new IllegalStateException("Activate " + owner + " first, before activating " + this); + } + if (LOG.isDebugEnabled()) { + LOG.debug("Activate: " + this); + } + isActive = true; + doActivate(); + if (getRootBinding().getSyncQueue().getTask(this) == null) { + enqueueSync((initialSyncDirection != null ? initialSyncDirection : SyncDirection.TO_MPS), true, callback); + } + notifyListeners(new _FunctionTypes._void_P1_E0() { + public void invoke(IListener l) { + l.bindingActivated(); + } + }); + } + + public final synchronized void deactivate(@Nullable Runnable callback) { + if (!(isActive)) { + return; + } + if (LOG.isDebugEnabled()) { + LOG.debug("Deactivate: " + this); + } + isActive = false; + for (Binding child : SetSequence.fromSet(ownedBindings)) { + child.deactivate(null); + } + doDeactivate(); + notifyListeners(new _FunctionTypes._void_P1_E0() { + public void invoke(IListener l) { + l.bindingDeactivated(); + } + }); + check_cvbvhu_a6a66(callback); + } + + protected abstract void doActivate(); + protected abstract void doDeactivate(); + + public void addListener(IListener l) { + ListSequence.fromList(listeners).addElement(l); + } + + public void removeListener(IListener l) { + ListSequence.fromList(listeners).removeElement(l); + } + + protected void notifyListeners(final _FunctionTypes._void_P1_E0 notifier) { + ListSequence.fromList(listeners).visitAll(new IVisitor() { + public void visit(IListener it) { + try { + notifier.invoke(it); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + }); + } + + public interface IListener { + void bindingAdded(Binding binding); + void bindingRemoved(Binding binding); + void ownerChanged(Binding newOwner); + void bindingActivated(); + void bindingDeactivated(); + } + private static boolean check_cvbvhu_a0a63(SyncTask checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.isRunning(); + } + return false; + } + private static void check_cvbvhu_a6a66(Runnable checkedDotOperand) { + if (null != checkedDotOperand) { + checkedDotOperand.run(); + } + + } + private static T as_cvbvhu_a0a0a16(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudDataDependency.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudDataDependency.java new file mode 100644 index 00000000..675186cf --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudDataDependency.java @@ -0,0 +1,12 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import de.q60.mps.incremental.runtime.DependencyKey; + +public class CloudDataDependency extends DependencyKey { + public static final CloudDataDependency INSTANCE = new CloudDataDependency(); + + private CloudDataDependency() { + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudIcons.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudIcons.java new file mode 100644 index 00000000..463c1f4c --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudIcons.java @@ -0,0 +1,19 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import javax.swing.Icon; +import java.awt.Color; + +/** + * Perhaps we need an Icon for Project? + */ +public class CloudIcons { + + public static final Icon ROOT_ICON = new LetterInSquareIcon("C", 14, 3.0f, 13.0f, Color.YELLOW, Color.BLACK); + public static final Icon MODEL_SERVER_ICON = new LetterInSquareIcon("S", 14, 3.0f, 13.0f, Color.YELLOW, Color.BLACK); + public static final Icon REPOSITORY_ICON = new LetterInSquareIcon("R", 14, 3.0f, 13.0f, Color.YELLOW, Color.BLACK); + public static final Icon BRANCH_ICON = new LetterInSquareIcon("B", 14, 3.0f, 13.0f, Color.YELLOW, Color.BLACK); + public static final Icon MODULE_ICON = new LetterInSquareIcon("M", 14, 2.0f, 13.0f, Color.YELLOW, Color.BLACK); + public static final Icon MODEL_ICON = new LetterInSquareIcon("m", 14, 2.0f, 12.0f, Color.YELLOW, Color.BLACK); +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudNodeTreeNodeCreationMethods.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudNodeTreeNodeCreationMethods.java new file mode 100644 index 00000000..d79da743 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudNodeTreeNodeCreationMethods.java @@ -0,0 +1,49 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.mps.openapi.language.SProperty; + +public class CloudNodeTreeNodeCreationMethods { + public CloudNodeTreeNodeCreationMethods() { + } + public static INode createProject(final CloudNodeTreeNode _this, String moduleName) { + // TODO check this represent a repository/a tree root + return PNodeAdapterCreationMethods.createProject(((PNodeAdapter) _this.getNode()), moduleName); + } + public static INode createModule(final CloudNodeTreeNode _this, String moduleName) { + // TODO check this represent a repository/a tree root + return PNodeAdapterCreationMethods.createModuleInRepository(((PNodeAdapter) _this.getNode()), moduleName); + } + public static INode createModel(final CloudNodeTreeNode _this, final String modelName) { + // TODO check this represent a module + return new PArea(_this.getBranch()).executeWrite(new Function0() { + public INode invoke() { + INode newModel = _this.getNode().addNewChild(LINKS.models$h3QT.getName(), -1, SConceptAdapter.wrap(CONCEPTS.Model$2P)); + newModel.setPropertyValue(PROPS.name$MnvL.getName(), modelName); + return newModel; + } + }); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink models$h3QT = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x69652614fd1c512L, "models"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Model$2P = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, "org.modelix.model.repositoryconcepts.structure.Model"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudRepository.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudRepository.java new file mode 100644 index 00000000..4310d6cb --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudRepository.java @@ -0,0 +1,373 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.api.IBranch; +import org.modelix.model.client.ActiveBranch; +import kotlin.jvm.functions.Function0; +import org.modelix.model.area.PArea; +import kotlin.Unit; +import java.util.function.Consumer; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.api.ITree; +import kotlin.jvm.functions.Function1; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.api.INode; +import org.modelix.model.mpsadapters.mps.NodeToSNodeAdapter; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.modelix.model.api.IReadTransaction; +import jetbrains.mps.project.MPSProject; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import java.util.Objects; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.modelix.model.api.IConcept; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; + +/** + * This pair (a ModelServer and a Repository) is equivalent to the coordinates of a git repository. + * The ModelServer is more like a collection of several git repositories. + */ +public class CloudRepository implements ICloudRepository { + + private final ModelServerConnection modelServer; + private final RepositoryId repositoryId; + + public CloudRepository(ModelServerConnection modelServer, RepositoryId repositoryId) { + if (modelServer == null) { + throw new IllegalArgumentException("modelServer should not be null"); + } + if (repositoryId == null) { + throw new IllegalArgumentException("repositoryId should not be null"); + } + this.modelServer = modelServer; + this.repositoryId = repositoryId; + } + + public IBranch getBranch() { + return getActiveBranch().getBranch(); + } + + public ActiveBranch getActiveBranch() { + return modelServer.getActiveBranch(repositoryId); + } + + public boolean isConnected() { + return modelServer.isConnected(); + } + + public RepositoryId getRepositoryId() { + return this.repositoryId; + } + public String presentation() { + if (modelServer.getBaseUrl().endsWith("/")) { + return modelServer.getBaseUrl() + getRepositoryId(); + } + return modelServer.getBaseUrl() + "/" + getRepositoryId(); + } + + public String completeId() { + if (modelServer.getBaseUrl().endsWith("/")) { + return modelServer.getBaseUrl() + repositoryId; + } + return modelServer.getBaseUrl() + "/" + repositoryId; + } + + public T computeRead(final Function0 producer) { + return modelServer.getInfoBranch().computeRead(new Function0() { + public T invoke() { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + return new PArea(branch).executeRead(new Function0() { + public T invoke() { + return producer.invoke(); + } + }); + } + }); + } + + public void runRead(final Runnable r) { + new PArea(modelServer.getInfoBranch()).executeRead(new Function0() { + public Unit invoke() { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + r.run(); + return Unit.INSTANCE; + } + }); + return Unit.INSTANCE; + } + }); + } + /** + * Consumer receives the root node + */ + public void runRead(final Consumer consumer) { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + final PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + consumer.accept(rootNode); + return Unit.INSTANCE; + } + }); + } + /** + * Computer receives the root node + * + * @param computer + * @param + * @return + */ + public T computeWrite(final Function1 computer) { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + final PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + return new PArea(branch).executeWrite(new Function0() { + public T invoke() { + return computer.invoke(rootNode); + } + }); + } + + /** + * Consuter receives the root node + */ + public void runWrite(final Consumer consumer) { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + final PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + new PArea(branch).executeWrite(new Function0() { + public Unit invoke() { + consumer.accept(rootNode); + return Unit.INSTANCE; + } + }); + } + + public void processProjects(final Consumer consumer) { + processRepoRoots(new Consumer() { + public void accept(INode iNode) { + SNode sNode = NodeToSNodeAdapter.wrap(iNode); + if (SNodeOperations.isInstanceOf(sNode, CONCEPTS.Project$An)) { + consumer.accept(SNodeOperations.cast(sNode, CONCEPTS.Project$An)); + } + } + }); + } + + public List repoRoots() { + final List roots = ListSequence.fromList(new ArrayList()); + processRepoRoots(new Consumer() { + public void accept(INode it) { + ListSequence.fromList(roots).addElement(it); + } + }); + return roots; + } + + public void processRepoRoots(final Consumer consumer) { + new PArea(modelServer.getInfoBranch()).executeRead(new Function0() { + public Unit invoke() { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + final PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + for (INode child : Sequence.fromIterable(rootNode.getAllChildren())) { + consumer.accept(child); + } + return Unit.INSTANCE; + } + }); + return Unit.INSTANCE; + } + }); + } + + public IReadTransaction getReadTransaction() { + return this.getActiveBranch().getBranch().getReadTransaction(); + } + + public RootBinding getRootBinding() { + return modelServer.getRootBinding(repositoryId); + } + + public ProjectBinding addProjectBinding(long nodeId, MPSProject project, SyncDirection initialSyncDirection) { + ProjectBinding binding = new ProjectBinding(project, nodeId, initialSyncDirection); + addBinding(binding); + return binding; + } + + public void addTransientModuleBinding(INode node) { + addBinding(new TransientModuleBinding(((PNodeAdapter) node).getNodeId())); + } + + public void addBinding(Binding binding) { + modelServer.addBinding(repositoryId, binding); + } + + public void deleteRoot(final INode root) { + new PArea(modelServer.getInfoBranch()).executeWrite(new Function0() { + public Unit invoke() { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + final PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + new PArea(branch).executeWrite(new Function0() { + public Unit invoke() { + rootNode.removeChild(root); + return Unit.INSTANCE; + } + }); + return Unit.INSTANCE; + } + }); + } + + public static CloudRepository fromPresentationString(String presentation) { + int lastSlash = presentation.lastIndexOf("/"); + String url = presentation.substring(0, lastSlash); + RepositoryId repositoryId = new RepositoryId(presentation.substring(lastSlash + 1)); + ModelServerConnection modelServer = ModelServerConnections.getInstance().ensureModelServerIsPresent(url); + return new CloudRepository(modelServer, repositoryId); + } + + public ModelServerConnection getModelServer() { + return this.modelServer; + } + + public INode createProject(final String name) { + return computeWrite(new Function1() { + public INode invoke(PNodeAdapter rootNode) { + INode newProject = rootNode.addNewChild(LINKS.projects$NW07.getName(), -1, SConceptAdapter.wrap(CONCEPTS.Project$An)); + newProject.setPropertyValue(PROPS.name$MnvL.getName(), name); + return newProject; + } + }); + } + public INode getProject(final String name) { + return computeRead(new Function0() { + public INode invoke() { + INode project = null; + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + for (INode child : Sequence.fromIterable(rootNode.getChildren(LINKS.projects$NW07.getName()))) { + String projectName = child.getPropertyValue(PROPS.name$MnvL.getName()); + if (Objects.equals(projectName, name)) { + project = child; + } + } + return project; + } + }); + } + + public boolean hasModuleUnderProject(final long projectNodeId, final String moduleId) { + return computeRead(new Function0() { + public Boolean invoke() { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + PNodeAdapter projectNode = new PNodeAdapter(projectNodeId, rootNode.getBranch()); + return ListSequence.fromList(INodeUtils.getChidlrenAsList(projectNode, LINKS.modules$Bi3g.getName())).any(new IWhereFilter() { + public boolean accept(INode it) { + return Objects.equals(it.getPropertyValue(PROPS.id$7MjP.getName()), moduleId); + } + }); + } + }); + } + public boolean hasModuleInRepository(final String moduleId) { + return computeRead(new Function0() { + public Boolean invoke() { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + return ListSequence.fromList(INodeUtils.getChidlrenAsList(rootNode, LINKS.modules$jBPn.getName())).any(new IWhereFilter() { + public boolean accept(INode it) { + return Objects.equals(it.getPropertyValue(PROPS.id$7MjP.getName()), moduleId); + } + }); + } + }); + } + + + public INode createModuleUnderProject(final long projectNodeId, final String moduleId, final String moduleName) { + return computeWrite(new Function1() { + public INode invoke(PNodeAdapter rootNode) { + PNodeAdapter projectNode = new PNodeAdapter(projectNodeId, rootNode.getBranch()); + INode newModule = projectNode.addNewChild(LINKS.modules$Bi3g.getName(), -1, SConceptAdapter.wrap(CONCEPTS.Module$4i)); + newModule.setPropertyValue(PROPS.id$7MjP.getName(), moduleId); + newModule.setPropertyValue(PROPS.name$MnvL.getName(), moduleName); + return newModule; + } + }); + } + + public INode createModuleUnderProject(INode cloudModule, String moduleId, String moduleName) { + return createModuleUnderProject(INodeUtils.nodeIdAsLong(cloudModule), moduleId, moduleName); + } + + public INode createNode(final INode parent, final SContainmentLink containmentLink, final IConcept concept, final Consumer initializer) { + return computeWrite(new Function1() { + public INode invoke(PNodeAdapter rootNode) { + INode newNode = parent.addNewChild(containmentLink.getName(), -1, concept); + initializer.accept(newNode); + return newNode; + } + }); + } + public INode createNode(INode parent, SContainmentLink containmentLink, SConcept concept, Consumer initializer) { + return createNode(parent, containmentLink, SConceptAdapter.wrap(concept), initializer); + } + + public INode createModule(final String moduleName) { + return this.computeWrite(new Function1() { + public INode invoke(PNodeAdapter rootNode) { + return PNodeAdapterCreationMethods.createModuleInRepository(rootNode, moduleName); + } + }); + } + @Override + public int hashCode() { + return this.modelServer.hashCode() + 7 * repositoryId.hashCode(); + } + @Override + public boolean equals(Object obj) { + if (obj instanceof CloudRepository) { + CloudRepository other = ((CloudRepository) obj); + return Objects.equals(this.modelServer, other.modelServer) && Objects.equals(this.repositoryId, other.repositoryId); + } else { + return false; + } + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Project$An = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, "org.modelix.model.repositoryconcepts.structure.Project"); + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink projects$NW07 = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x620a8558361d3e0cL, "projects"); + /*package*/ static final SContainmentLink modules$Bi3g = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, 0x37a0917d689de9e2L, "modules"); + /*package*/ static final SContainmentLink modules$jBPn = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x69652614fd1c517L, "modules"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$7MjP = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x3aa34013f2a802e0L, "id"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModel.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModel.java new file mode 100644 index 00000000..8e7755f3 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModel.java @@ -0,0 +1,112 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import jetbrains.mps.smodel.EditableModelDescriptor; +import org.jetbrains.mps.openapi.model.EditableSModel; +import jetbrains.mps.extapi.model.TransientSModel; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.model.util.pmap.CustomPMap; +import org.modelix.model.util.pmap.SmallPMap; +import org.jetbrains.mps.openapi.model.SModelId; +import org.jetbrains.mps.openapi.persistence.NullDataSource; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.smodel.ModelLoadResult; +import jetbrains.mps.smodel.SModel; +import jetbrains.mps.smodel.SNodeUndoableAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.command.CommandProcessor; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.ide.project.ProjectHelper; +import org.jetbrains.mps.openapi.model.SNode; +import com.intellij.openapi.editor.Document; +import jetbrains.mps.ide.undo.MPSUndoUtil; +import org.apache.log4j.Level; +import jetbrains.mps.smodel.loading.ModelLoadingState; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.mps.openapi.module.SModuleReference; +import org.jetbrains.mps.openapi.persistence.PersistenceFacade; + +public class CloudTransientModel extends EditableModelDescriptor implements EditableSModel, IUserObjectContainer, TransientSModel { + private static final Logger LOG = LogManager.getLogger(CloudTransientModel.class); + + private CustomPMap userObjects = SmallPMap.Companion.empty(); + + public CloudTransientModel(CloudTransientModule module, String name, SModelId modelId, long modelNodeId) { + super(createModelRef(name, module.getModuleReference(), modelId), new NullDataSource()); + } + + public void dispose() { + } + + @Override + public T getUserObject(UserObjectKey key) { + return (T) userObjects.get(key); + } + @Override + public void putUserObject(UserObjectKey key, T value) { + userObjects = userObjects.put(key, value); + } + @Override + public void updateTimestamp() { + } + @Override + public boolean needsReloading() { + return false; + } + @NotNull + @Override + protected ModelLoadResult createModel() { + SModel smodel = new SModel(getReference()) { + @Override + protected void performUndoableAction(@NotNull SNodeUndoableAction action) { + try { + Project project = CommandProcessor.getInstance().getCurrentCommandProject(); + if (project == null) { + return; + } + SRepository repository = ProjectHelper.getProjectRepository(project); + if (repository == null) { + return; + } + SNode affectedNode = action.getAffectedNode(); + if (affectedNode == null) { + return; + } + SNode rootNode = affectedNode.getContainingRoot(); + Document doc = MPSUndoUtil.getDoc(repository, rootNode.getReference()); + MpsReplicatedRepository.documentChanged(MPSUndoUtil.getRefForDoc(doc)); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + }; + return new ModelLoadResult(smodel, ModelLoadingState.FULLY_LOADED); + } + @Override + public boolean isChanged() { + return false; + } + @Override + public void save() { + } + @Override + public void rename(String newModelName, boolean changeFile) { + throw new UnsupportedOperationException(); + } + @Override + public boolean isReadOnly() { + return false; + } + @Override + public void reloadFromSource() { + throw new UnsupportedOperationException(); + } + private static SModelReference createModelRef(String modelName, SModuleReference moduleReference, SModelId modelId) { + return PersistenceFacade.getInstance().createModelReference(moduleReference, modelId, modelName); + } + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModule.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModule.java new file mode 100644 index 00000000..63d84f48 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModule.java @@ -0,0 +1,50 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import jetbrains.mps.project.AbstractModule; +import jetbrains.mps.extapi.module.TransientSModule; +import jetbrains.mps.project.structure.modules.ModuleDescriptor; +import org.modelix.model.util.pmap.CustomPMap; +import org.modelix.model.util.pmap.SmallPMap; +import jetbrains.mps.project.ModuleId; +import jetbrains.mps.vfs.IFile; +import org.jetbrains.annotations.Nullable; +import java.util.Set; + +public class CloudTransientModule extends AbstractModule implements IUserObjectContainer, TransientSModule { + private final ModuleDescriptor myDescriptor; + private CustomPMap userObjects = SmallPMap.Companion.empty(); + + public CloudTransientModule(String name, ModuleId id) { + super((IFile) null); + myDescriptor = new ModuleDescriptor(); + myDescriptor.setId(id); + myDescriptor.setNamespace(name); + setModuleReference(myDescriptor.getModuleReference()); + } + @Override + public T getUserObject(UserObjectKey key) { + return (T) userObjects.get(key); + } + @Override + public void putUserObject(UserObjectKey key, T value) { + userObjects = userObjects.put(key, value); + } + @Nullable + @Override + public ModuleDescriptor getModuleDescriptor() { + return myDescriptor; + } + @Override + protected void collectMandatoryFacetTypes(Set types) { + } + @Override + public boolean isPackaged() { + return false; + } + @Override + public boolean isReadOnly() { + return false; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModules.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModules.java new file mode 100644 index 00000000..f7a7ad9f --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CloudTransientModules.java @@ -0,0 +1,105 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import jetbrains.mps.smodel.MPSModuleRepository; +import jetbrains.mps.extapi.module.SRepositoryExt; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.smodel.MPSModuleOwner; +import org.jetbrains.mps.openapi.module.SModuleId; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import jetbrains.mps.project.ModuleId; +import org.jetbrains.mps.openapi.model.SModel; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.apache.log4j.Level; + +public class CloudTransientModules { + private static final Logger LOG = LogManager.getLogger(CloudTransientModules.class); + + private static CloudTransientModules ourInstance = new CloudTransientModules(MPSModuleRepository.getInstance()); + + public static CloudTransientModules getInstance() { + return ourInstance; + } + + private SRepositoryExt mpsRepository; + private List modules = ListSequence.fromList(new ArrayList()); + private final MPSModuleOwner moduleOwner = new MPSModuleOwner() { + public boolean isHidden() { + return false; + } + }; + + public CloudTransientModules(SRepositoryExt mpsRepository) { + this.mpsRepository = mpsRepository; + } + + public boolean isModuleIdUsed(final SModuleId moduleId) { + final Wrappers._boolean result = new Wrappers._boolean(); + mpsRepository.getModelAccess().runReadAction(new Runnable() { + public void run() { + result.value = CloudTransientModules.this.mpsRepository.getModule(moduleId) != null; + } + }); + return result.value; + } + + public CloudTransientModule createModule(final String name, final ModuleId id) { + final Wrappers._T module = new Wrappers._T(null); + mpsRepository.getModelAccess().runWriteAction(new Runnable() { + public void run() { + module.value = new CloudTransientModule(name, id); + ListSequence.fromList(modules).addElement(module.value); + if (LOG.isDebugEnabled()) { + LOG.debug("Register module " + id); + } + mpsRepository.registerModule(module.value, moduleOwner); + } + }); + return module.value; + } + + public void disposeModule(final CloudTransientModule module) { + mpsRepository.getModelAccess().runWriteAction(new Runnable() { + public void run() { + doDisposeModule(module); + ListSequence.fromList(modules).removeElement(module); + } + }); + } + + protected void doDisposeModule(CloudTransientModule module) { + if (module.getRepository() != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Unregister module " + module.getModuleId()); + } + mpsRepository.unregisterModule(module, moduleOwner); + } + Iterable models = module.getModels(); + for (CloudTransientModel model : Sequence.fromIterable(models).ofType(CloudTransientModel.class)) { + model.dispose(); + } + } + + public void dispose() { + WriteAccessUtil.runWrite(mpsRepository, new Runnable() { + public void run() { + try { + for (CloudTransientModule module : ListSequence.fromList(modules)) { + doDisposeModule(module); + } + ListSequence.fromList(modules).clear(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + }); + } + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CommandHelper.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CommandHelper.java new file mode 100644 index 00000000..ba6c0624 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/CommandHelper.java @@ -0,0 +1,123 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import javax.swing.Timer; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import jetbrains.mps.project.Project; +import java.util.List; +import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.apache.log4j.Level; +import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import jetbrains.mps.ide.ThreadUtils; +import com.intellij.openapi.application.ApplicationManager; +import org.jetbrains.mps.openapi.module.SRepository; +import org.jetbrains.mps.openapi.module.ModelAccess; +import jetbrains.mps.project.ProjectManager; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.smodel.MPSModuleRepository; + +public class CommandHelper { + private static final Logger LOG = LogManager.getLogger(CommandHelper.class); + + private static Timer timer = new Timer(10, new ActionListener() { + public void actionPerformed(ActionEvent e) { + Project project = getProject(); + if (project == null) { + return; + } + timer.stop(); + List> queueCopy = ListSequence.fromListWithValues(new ArrayList>(), queue); + ListSequence.fromList(queue).clear(); + for (Tuples._2 entry : ListSequence.fromList(queueCopy)) { + try { + executeCommand(project.getRepository(), (boolean) entry._1(), entry._0()); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + } + }); + private static List> queue = ListSequence.fromList(new ArrayList>()); + + public static void runInCommand(Runnable runnable) { + runInCommand(runnable, false); + } + + public static void runInUndoTransparentCommand(Runnable runnable) { + runInCommand(runnable, true); + } + + public static void runInCommand(final Runnable runnable, final boolean undoTransparent) { + final Project project = getProject(); + if (project == null) { + ListSequence.fromList(queue).addElement(MultiTuple.from(runnable, undoTransparent)); + if (!(timer.isRunning())) { + timer.start(); + } + } else { + final Wrappers._T ex = new Wrappers._T(null); + final Runnable runnableWithExceptionHandling = new Runnable() { + public void run() { + try { + runnable.run(); + } catch (Throwable t) { + ex.value = t; + } + } + }; + if (ThreadUtils.isInEDT()) { + executeCommand(project.getRepository(), undoTransparent, runnableWithExceptionHandling); + } else { + ApplicationManager.getApplication().invokeAndWait(new Runnable() { + public void run() { + executeCommand(project.getRepository(), undoTransparent, runnableWithExceptionHandling); + } + }); + } + if (ex.value != null) { + throw new RuntimeException("Exception in command", ex.value); + } + } + } + + public static void executeCommand(SRepository repository, boolean undoTransparent, Runnable runnable) { + ThreadUtils.assertEDT(); + + ModelAccess modelAccess = repository.getModelAccess(); + if (modelAccess.canWrite()) { + runnable.run(); + } else { + if (undoTransparent) { + modelAccess.executeUndoTransparentCommand(runnable); + } else { + modelAccess.executeCommand(runnable); + } + } + } + + protected static Project getProject() { + List projects = ProjectManager.getInstance().getOpenedProjects(); + return ListSequence.fromList(projects).first(); + } + + public static SRepository getSRepository() { + List openedProjects = ProjectManager.getInstance().getOpenedProjects(); + SRepository projectRepo = ListSequence.fromList(openedProjects).select(new ISelector() { + public SRepository select(Project it) { + return it.getRepository(); + } + }).where(new NotNullWhereFilter()).first(); + return (projectRepo != null ? projectRepo : MPSModuleRepository.getInstance()); + } + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ELockType.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ELockType.java new file mode 100644 index 00000000..6580aee2 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ELockType.java @@ -0,0 +1,11 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + + +public enum ELockType { + MPS_COMMAND(), + MPS_READ(), + CLOUD_WRITE(), + CLOUD_READ() +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ForeignNodeReference.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ForeignNodeReference.java new file mode 100644 index 00000000..4a45717d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ForeignNodeReference.java @@ -0,0 +1,124 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.INodeReference; +import org.modelix.model.api.INode; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.area.IArea; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.modelix.model.mpsadapters.mps.SNodeToNodeAdapter; +import org.jetbrains.mps.openapi.model.SNodeReference; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.mps.openapi.model.SNodeId; +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.mps.openapi.module.SRepository; +import org.jetbrains.mps.openapi.model.SModel; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPointerOperations; +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.Objects; +import org.modelix.model.lazy.INodeReferenceSerializer; +import org.jetbrains.annotations.NotNull; + +public class ForeignNodeReference implements INodeReference { + + private String modelName; + private String foreignId; + + public ForeignNodeReference(String modelName, String foreignId) { + this.modelName = modelName; + this.foreignId = foreignId; + } + + public String getModelName() { + return modelName; + } + + public String getForeignId() { + return foreignId; + } + + @Override + public INode resolveNode(@Nullable IArea area) { + MPSModuleRepository repo = MPSModuleRepository.getInstance(); + return SNodeToNodeAdapter.wrap(check_e0to5m_a0b0k(getReference(repo), repo, this)); + } + + private class SimpleSNodeReference implements SNodeReference { + + private SModelReference sModelReference; + private SNodeId sNodeId; + + private SimpleSNodeReference(SModelReference sModelReference, SNodeId sNodeId) { + this.sModelReference = sModelReference; + this.sNodeId = sNodeId; + } + + @Nullable + @Override + public SNode resolve(SRepository repository) { + SModel model = SPointerOperations.resolveModel(getModelReference(), repository); + return model.getNode(getNodeId()); + } + @Nullable + @Override + public SModelReference getModelReference() { + return this.sModelReference; + } + @Nullable + @Override + public SNodeId getNodeId() { + return this.sNodeId; + } + } + + public SNodeReference getReference(SRepository repository) { + if (repository == null) { + throw new IllegalArgumentException("repository should not be null"); + } + SModelReference sModelReference = null; + for (SModule module : Sequence.fromIterable(repository.getModules())) { + for (SModel itModel : ListSequence.fromList(SModuleUtils.getModelsWithoutDescriptor(module))) { + if (Objects.equals(itModel.getModelName(), modelName)) { + sModelReference = itModel.getReference(); + } + } + } + SNodeId sNodeId = new jetbrains.mps.smodel.SNodeId.Foreign("~" + foreignId); + return new SimpleSNodeReference(sModelReference, sNodeId); + } + + public static class ForeignNodeReferenceSerializer implements INodeReferenceSerializer { + @Nullable + @Override + public String serialize(@NotNull INodeReference nr) { + if (nr instanceof ForeignNodeReference) { + ForeignNodeReference fnr = ((ForeignNodeReference) nr); + return "->" + fnr.getModelName() + ":" + fnr.getForeignId(); + } else { + return null; + } + } + @Nullable + @Override + public INodeReference deserialize(@NotNull String refValueAsString) { + if (refValueAsString.startsWith("->")) { + String res = refValueAsString.substring("->".length()); + String modelName = res.split(":")[0]; + String foreignId = res.split(":")[1]; + INodeReference refValue = new ForeignNodeReference(modelName, foreignId); + return refValue; + } else { + return null; + } + } + } + private static SNode check_e0to5m_a0b0k(SNodeReference checkedDotOperand, MPSModuleRepository repo, ForeignNodeReference checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.resolve(repo); + } + return null; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ICloudRepository.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ICloudRepository.java new file mode 100644 index 00000000..292525af --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ICloudRepository.java @@ -0,0 +1,14 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.IBranch; +import org.modelix.model.client.IIndirectBranch; +import org.modelix.model.lazy.RepositoryId; + +public interface ICloudRepository { + IBranch getBranch(); + IIndirectBranch getActiveBranch(); + String completeId(); + RepositoryId getRepositoryId(); +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/INodeUtils.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/INodeUtils.java new file mode 100644 index 00000000..b722dd33 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/INodeUtils.java @@ -0,0 +1,164 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.api.IConcept; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import jetbrains.mps.internal.collections.runtime.Sequence; +import java.util.Objects; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.LinkedList; +import org.jetbrains.mps.openapi.language.SProperty; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; +import org.modelix.model.api.IProperty; +import org.modelix.model.api.IChildLink; +import org.modelix.model.api.IReferenceLink; +import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class INodeUtils { + public INodeUtils() { + } + public static long nodeIdAsLong(final INode _this) { + PNodeAdapter cloudProjectAsPNodeAdapter = ((PNodeAdapter) _this); + long nodeId = cloudProjectAsPNodeAdapter.getNodeId(); + return nodeId; + } + public static INode containingModule(final INode _this) { + if (INodeUtils.isModule(_this)) { + return _this; + } + INode parent = _this.getParent(); + if (parent == null) { + return null; + } + return INodeUtils.containingModule(parent); + } + public static INode containingModel(final INode _this) { + if (INodeUtils.isModel(_this)) { + return _this; + } + INode parent = _this.getParent(); + if (parent == null) { + return null; + } + return INodeUtils.containingModel(parent); + } + public static boolean isModule(final INode _this) { + IConcept concept = _this.getConcept(); + if (concept == null) { + return false; + } + return concept.isSubConceptOf(SConceptAdapter.wrap(CONCEPTS.Module$4i)); + } + public static boolean isModel(final INode _this) { + IConcept concept = _this.getConcept(); + if (concept == null) { + return false; + } + return concept.isSubConceptOf(SConceptAdapter.wrap(CONCEPTS.Model$2P)); + } + public static INode findChildByName(final INode _this, String name) { + for (INode child : Sequence.fromIterable(_this.getAllChildren())) { + if (Objects.equals(child.getPropertyValue("name"), name)) { + return child; + } + } + return null; + } + public static List getChidlrenAsList(final INode _this, String role) { + List nodes = ListSequence.fromList(new LinkedList()); + for (INode node : Sequence.fromIterable(_this.getChildren(role))) { + ListSequence.fromList(nodes).addElement(node); + } + return nodes; + } + public static void removeAllChildrenWithRole(final INode _this, String role) { + List nodes = ListSequence.fromList(new LinkedList()); + for (INode node : Sequence.fromIterable(_this.getChildren(role))) { + ListSequence.fromList(nodes).addElement(node); + } + for (INode child : ListSequence.fromList(nodes)) { + _this.removeChild(child); + } + } + public static void copyProperty(final INode _this, INode original, String propertyName) { + try { + _this.setPropertyValue(propertyName, original.getPropertyValue(propertyName)); + } catch (Exception e) { + throw new RuntimeException("Unable to copy property " + propertyName + " from " + original + " to " + _this, e); + } + } + public static void copyProperty(final INode _this, INode original, SProperty property) { + try { + _this.setPropertyValue(property.getName(), original.getPropertyValue(property.getName())); + } catch (Exception e) { + throw new RuntimeException("Unable to copy property " + property.getName() + " from " + original + " to " + _this, e); + } + } + public static void copyPropertyIfNecessary(final INode _this, INode original, SProperty property) { + if (Objects.equals(original.getPropertyValue(property.getName()), _this.getPropertyValue(property.getName()))) { + return; + } + INodeUtils.copyProperty(_this, original, property); + } + public static INode replicateChild(final INode _this, String role, INode original) { + try { + Map equivalenceMap = MapSequence.fromMap(new HashMap()); + List> postponedReferencesAssignments = ListSequence.fromList(new LinkedList>()); + INode result = INodeUtils.replicateChildHelper(_this, role, original, equivalenceMap, postponedReferencesAssignments); + for (Tuples._3 postponedRefAssignment : ListSequence.fromList(postponedReferencesAssignments)) { + INode target = postponedRefAssignment._2(); + if (MapSequence.fromMap(equivalenceMap).containsKey(target)) { + target = MapSequence.fromMap(equivalenceMap).get(target); + } + postponedRefAssignment._0().setReferenceTarget(postponedRefAssignment._1(), target); + } + return result; + } catch (Exception e) { + throw new RuntimeException("Unable to replicate child in role " + role + ". Original: " + original + ", This: " + _this, e); + } + } + public static void cloneChildren(final INode _this, INode original, String role) { + INodeUtils.removeAllChildrenWithRole(_this, role); + for (INode originalChild : Sequence.fromIterable(original.getChildren(role))) { + INodeUtils.replicateChild(_this, role, originalChild); + } + } + public static INode replicateChildHelper(final INode _this, String role, INode original, Map equivalenceMap, List> postponedReferencesAssignments) { + IConcept concept = original.getConcept(); + INode copy = null; + try { + copy = _this.addNewChild(role, -1, concept); + } catch (Exception e) { + throw new RuntimeException("Unable to add child to " + _this + " with role " + role + " and concept " + concept, e); + } + for (IProperty property : ListSequence.fromList(concept.getAllProperties())) { + copy.setPropertyValue(property.getName(), original.getPropertyValue(property.getName())); + } + for (IChildLink childLink : ListSequence.fromList(concept.getAllChildLinks())) { + for (INode child : ListSequence.fromList(INodeUtils.getChidlrenAsList(original, childLink.getName()))) { + INodeUtils.replicateChildHelper(copy, childLink.getName(), child, equivalenceMap, postponedReferencesAssignments); + } + } + for (IReferenceLink refLink : ListSequence.fromList(concept.getAllReferenceLinks())) { + INode target = original.getReferenceTarget(refLink.getName()); + if (target != null) { + ListSequence.fromList(postponedReferencesAssignments).addElement(MultiTuple.from(copy, refLink.getName(), target)); + } + } + return copy; + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + /*package*/ static final SConcept Model$2P = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, "org.modelix.model.repositoryconcepts.structure.Model"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/IUserObjectContainer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/IUserObjectContainer.java new file mode 100644 index 00000000..0ecd90ac --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/IUserObjectContainer.java @@ -0,0 +1,9 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + + +public interface IUserObjectContainer { + void putUserObject(UserObjectKey key, T value); + T getUserObject(UserObjectKey key); +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/IterableOfINodeUtils.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/IterableOfINodeUtils.java new file mode 100644 index 00000000..188e2bff --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/IterableOfINodeUtils.java @@ -0,0 +1,28 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import java.util.List; +import org.modelix.model.api.INode; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.LinkedList; +import java.util.Iterator; + +public class IterableOfINodeUtils { + public IterableOfINodeUtils() { + } + public static List toList(final Iterable _this) { + List res = ListSequence.fromList(new LinkedList()); + for (Iterator it = _this.iterator(); it.hasNext();) { + ListSequence.fromList(res).addElement(it.next()); + } + return res; + } + public static List toCastedList(final Iterable _this) { + List res = ListSequence.fromList(new LinkedList()); + for (Iterator it = _this.iterator(); it.hasNext();) { + ListSequence.fromList(res).addElement(((T) it.next())); + } + return res; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/LetterInSquareIcon.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/LetterInSquareIcon.java new file mode 100644 index 00000000..e08db6c9 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/LetterInSquareIcon.java @@ -0,0 +1,53 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import javax.swing.Icon; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.RoundRectangle2D; +import java.awt.Font; + +public class LetterInSquareIcon implements Icon { + private String letter; + private int fontSize; + private float offsetX; + private float offsetY; + private Color backgroundColor; + private Color foregroundColor; + public LetterInSquareIcon(String letter, int fontSize, float offsetX, float offsetY) { + this(letter, fontSize, offsetX, offsetY, Color.BLACK, new Color(200, 200, 200)); + } + public LetterInSquareIcon(String letter, int fontSize, float offsetX, float offsetY, Color backgroundColor, Color foregroundColor) { + this.letter = letter; + this.fontSize = fontSize; + this.offsetX = offsetX; + this.offsetY = offsetY; + this.backgroundColor = backgroundColor; + this.foregroundColor = foregroundColor; + } + public void paintIcon(Component p0, Graphics g_, int x, int y) { + Graphics2D g = (Graphics2D) g_.create(); + try { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + g.setColor(backgroundColor); + g.fill(new RoundRectangle2D.Double(x, y, getIconWidth(), getIconHeight(), 5, 5)); + g.setFont(new Font("Arial", Font.BOLD, fontSize)); + g.setColor(foregroundColor); + g.drawString(letter, x + offsetX, y + offsetY); + } finally { + g.dispose(); + } + } + public int getIconWidth() { + return 16; + } + public int getIconHeight() { + return 16; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MPSNodeMapping.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MPSNodeMapping.java new file mode 100644 index 00000000..26dfa9d8 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MPSNodeMapping.java @@ -0,0 +1,25 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.model.SNode; + +public class MPSNodeMapping { + private static final String MPS_NODE_ID_PROPERTY_NAME = ModelSynchronizer.MPS_NODE_ID_PROPERTY_NAME; + public MPSNodeMapping() { + } + public static void mapToMpsNode(final INode _this, SNode mpsNode) { + _this.setPropertyValue(MPS_NODE_ID_PROPERTY_NAME, mpsNode.getNodeId().toString()); + } + public static String mappedMpsNodeID(final INode _this) { + try { + return _this.getPropertyValue(MPS_NODE_ID_PROPERTY_NAME); + } catch (RuntimeException e) { + throw new RuntimeException("Failed to retrieve the " + MPS_NODE_ID_PROPERTY_NAME + " property in mappedMpsNodeID. The INode is " + _this + ", concept: " + _this.getConcept(), e); + } + } + public static boolean isMappedToMpsNode(final INode _this) { + return MPSNodeMapping.mappedMpsNodeID(_this) != null; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MPSProjectUtils.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MPSProjectUtils.java new file mode 100644 index 00000000..552fd5cc --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MPSProjectUtils.java @@ -0,0 +1,59 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.project.MPSProject; +import jetbrains.mps.project.ModuleId; +import java.io.File; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.LocalFileSystem; +import java.io.IOException; +import jetbrains.mps.vfs.IFile; +import de.slisson.mps.reflection.runtime.ReflectionUtil; +import jetbrains.mps.ide.newSolutionDialog.NewModuleUtil; +import jetbrains.mps.project.MPSExtentions; +import jetbrains.mps.project.structure.modules.SolutionDescriptor; +import jetbrains.mps.project.Solution; +import jetbrains.mps.smodel.GeneralModuleFactory; +import jetbrains.mps.lang.migration.runtime.base.VersionFixer; + +public class MPSProjectUtils { + public MPSProjectUtils() { + } + public static SModule createModule(final MPSProject _this, String nameSpace, ModuleId moduleId, Object requestor) { + if (nameSpace == null) { + throw new IllegalArgumentException("nameSpace should not be null"); + } + + // A module may already exist in the global repository, but is just not part of the project yet. + SModule existingModule = _this.getRepository().getModule(moduleId); + if (existingModule != null) { + _this.addModule(existingModule); + return existingModule; + } + + File moduleFolder = new File(_this.getProjectFile(), nameSpace); + VirtualFile moduleFolder_ = LocalFileSystem.getInstance().findFileByIoFile(moduleFolder); + if (moduleFolder_ != null && moduleFolder_.exists()) { + try { + moduleFolder_.delete(requestor); + } catch (IOException e) { + throw new RuntimeException("Failed to delete " + moduleFolder_, e); + } + } + + IFile descriptorFile = (IFile) ReflectionUtil.callStaticMethod(NewModuleUtil.class, "getModuleFile", new Class[]{String.class, String.class, String.class}, new Object[]{nameSpace, moduleFolder.getAbsolutePath(), MPSExtentions.DOT_SOLUTION}); + if (descriptorFile == null) { + throw new IllegalStateException("descriptor file should not be null"); + } + SolutionDescriptor descriptor = (SolutionDescriptor) ReflectionUtil.callStaticMethod(NewModuleUtil.class, "createNewSolutionDescriptor", new Class[]{String.class, IFile.class}, new Object[]{nameSpace, descriptorFile}); + + descriptor.setId(moduleId); + Solution module = (Solution) new GeneralModuleFactory().instantiate(descriptor, descriptorFile); + _this.addModule(module); + new VersionFixer(_this, module, false).updateImportVersions(); + module.save(); + return module; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MessageHandler.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MessageHandler.java new file mode 100644 index 00000000..d144d886 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MessageHandler.java @@ -0,0 +1,10 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.java_websocket.WebSocket; +import org.json.JSONObject; + +public interface MessageHandler { + void handle(WebSocket conn, JSONObject message); +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MetaModelSynchronizer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MetaModelSynchronizer.java new file mode 100644 index 00000000..dca7bb9a --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MetaModelSynchronizer.java @@ -0,0 +1,7 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + + +public class MetaModelSynchronizer { +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelAccess.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelAccess.java new file mode 100644 index 00000000..6855798f --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelAccess.java @@ -0,0 +1,33 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.module.SRepository; +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.project.Project; +import jetbrains.mps.project.SModuleOperations; + +public class ModelAccess { + public ModelAccess() { + } + public static void runInWriteActionIfNeeded(final SModel _this, final Runnable runnable) { + SRepository repo = null; + SModule module = _this.getModule(); + if (module != null) { + Project project = SModuleOperations.getProjectForModule(module); + if (project != null) { + repo = project.getRepository(); + } + } + if (repo == null) { + runnable.run(); + } else { + repo.getModelAccess().runWriteAction(new Runnable() { + public void run() { + runnable.run(); + } + }); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelBinding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelBinding.java new file mode 100644 index 00000000..d383cd70 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelBinding.java @@ -0,0 +1,520 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.jetbrains.mps.openapi.model.SModel; +import java.util.Set; +import org.modelix.model.operations.RoleInNode; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import gnu.trove.set.hash.TLongHashSet; +import org.jetbrains.mps.openapi.model.SNodeChangeListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.event.SPropertyChangeEvent; +import org.modelix.model.api.IBranch; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.modelix.model.api.IWriteTransaction; +import org.apache.log4j.Level; +import org.jetbrains.mps.openapi.event.SReferenceChangeEvent; +import org.jetbrains.mps.openapi.event.SNodeAddEvent; +import org.jetbrains.mps.openapi.event.SNodeRemoveEvent; +import jetbrains.mps.smodel.event.SModelListener; +import jetbrains.mps.smodel.event.SModelLanguageEvent; +import jetbrains.mps.smodel.event.SModelDevKitEvent; +import jetbrains.mps.smodel.event.SModelChildEvent; +import jetbrains.mps.smodel.event.SModelRenamedEvent; +import jetbrains.mps.smodel.event.SModelRootEvent; +import jetbrains.mps.smodel.event.SModelImportEvent; +import jetbrains.mps.smodel.loading.ModelLoadingState; +import jetbrains.mps.smodel.event.SModelPropertyEvent; +import jetbrains.mps.smodel.event.SModelReferenceEvent; +import jetbrains.mps.smodel.SModelInternal; +import org.modelix.model.api.ITree; +import org.jetbrains.mps.openapi.model.SNode; +import jetbrains.mps.internal.collections.runtime.Sequence; +import gnu.trove.procedure.TLongProcedure; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.ITreeChangeVisitor; +import org.modelix.model.api.ITreeChangeVisitorEx; +import java.util.Objects; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class ModelBinding extends Binding { + private static final Logger LOG = LogManager.getLogger(ModelBinding.class); + + private SModel model; + protected final long modelNodeId; + private Set childrenSyncToMPSRequired = SetSequence.fromSet(new HashSet()); + private Set referenceSyncToMPSRequired = SetSequence.fromSet(new HashSet()); + private Set propertySyncToMPSRequired = SetSequence.fromSet(new HashSet()); + private TLongHashSet fullNodeSyncToMPSRequired = new TLongHashSet(); + private boolean modelPropertiesSyncToMPSRequired = true; + private ModelSynchronizer synchronizer; + private SNodeChangeListener nodeChangeListener = new SNodeChangeListener() { + @Override + public void propertyChanged(@NotNull final SPropertyChangeEvent e) { + try { + if (isSynchronizing()) { + return; + } + final IBranch branch = getBranch(); + new PArea(branch).executeWrite(new Function0() { + public Unit invoke() { + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + IWriteTransaction t = branch.getWriteTransaction(); + long id = synchronizer.getOrSyncToCloud(e.getNode(), t); + if (id != 0L && t.containsNode(id)) { + t.setProperty(id, e.getProperty().getName(), e.getNewValue()); + } + } + }); + return Unit.INSTANCE; + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + + @Override + public void referenceChanged(@NotNull final SReferenceChangeEvent e) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.handleReferenceChanged(e); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + + @Override + public void nodeAdded(@NotNull final SNodeAddEvent e) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.handleMPSNodeAdded(e); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + + @Override + public void nodeRemoved(@NotNull final SNodeRemoveEvent e) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.handleMPSNodeRemoved(e); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + }; + private SModelListener modelListener = new SModelListener() { + + @Override + public void languageAdded(SModelLanguageEvent event) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.syncUsedLanguagesAndDevKitsFromMPS(); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + @Override + public void languageRemoved(SModelLanguageEvent event) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.syncUsedLanguagesAndDevKitsFromMPS(); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + @Override + public void devkitAdded(SModelDevKitEvent event) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.syncUsedLanguagesAndDevKitsFromMPS(); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + @Override + public void devkitRemoved(SModelDevKitEvent event) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.syncUsedLanguagesAndDevKitsFromMPS(); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + + @Override + public void beforeChildRemoved(SModelChildEvent event) { + } + @Override + public void beforeModelDisposed(SModel model) { + } + @Override + public void beforeModelRenamed(SModelRenamedEvent event) { + } + @Override + public void beforeRootRemoved(SModelRootEvent event) { + } + @Override + public void childAdded(SModelChildEvent event) { + } + @Override + public void childRemoved(SModelChildEvent event) { + } + @NotNull + @Override + public SModelListener.SModelListenerPriority getPriority() { + return SModelListener.SModelListenerPriority.CLIENT; + } + @Override + public void importAdded(SModelImportEvent event) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.syncModelImportsFromMPS(); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + @Override + public void importRemoved(SModelImportEvent event) { + try { + if (isSynchronizing()) { + return; + } + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + synchronizer.syncModelImportsFromMPS(); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + @Override + public void modelLoadingStateChanged(SModel model, ModelLoadingState state) { + } + @Override + public void modelRenamed(SModelRenamedEvent event) { + } + @Override + public void modelSaved(SModel model) { + } + @Override + public void propertyChanged(SModelPropertyEvent event) { + } + @Override + public void referenceAdded(SModelReferenceEvent event) { + } + @Override + public void referenceRemoved(SModelReferenceEvent event) { + } + @Deprecated + @Override + public void rootAdded(SModelRootEvent event) { + } + @Deprecated + @Override + public void rootRemoved(SModelRootEvent event) { + } + }; + + public ModelBinding(long modelNodeId, SModel model, SyncDirection initialSyncDirection) { + super(initialSyncDirection); + this.model = model; + this.modelNodeId = modelNodeId; + } + + public SModel getModel() { + return this.model; + } + + public long getModelNodeId() { + return this.modelNodeId; + } + + @Override + public String toString() { + return "Model: " + Long.toHexString(modelNodeId) + " -> " + model.getName().getValue(); + } + + @Override + protected void doActivate() { + synchronizer = new ModelSynchronizer(modelNodeId, model, getCloudRepository()); + model.addChangeListener(nodeChangeListener); + ((SModelInternal) model).addModelListener(modelListener); + } + @Override + protected void doDeactivate() { + model.removeChangeListener(nodeChangeListener); + ((SModelInternal) model).removeModelListener(modelListener); + synchronizer = null; + } + @Override + public void doSyncToCloud(IWriteTransaction t) { + synchronizer.fullSyncFromMPS(); + } + @Override + protected void doSyncToMPS(@NotNull final ITree tree) { + if (runningTask.isInitialSync) { + Iterable mpsRootNodes = model.getRootNodes(); + Iterable cloudRootNodes = tree.getChildren(modelNodeId, LINKS.rootNodes$jxXY.getName()); + if (Sequence.fromIterable(mpsRootNodes).isNotEmpty() && Sequence.fromIterable(cloudRootNodes).isEmpty()) { + // TODO remove this workaround + forceEnqueueSyncTo(SyncDirection.TO_CLOUD, true, null); + } else { + synchronizer.syncModelToMPS(tree, false); + } + } else { + synchronizer.runAndFlushReferences(new Runnable() { + public void run() { + for (RoleInNode roleInNode : SetSequence.fromSet(childrenSyncToMPSRequired)) { + try { + if (tree.containsNode(roleInNode.getNodeId())) { + synchronizer.syncChildrenToMPS(roleInNode.getNodeId(), roleInNode.getRole(), tree, false); + } + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + SetSequence.fromSet(childrenSyncToMPSRequired).clear(); + + for (RoleInNode roleInNode : SetSequence.fromSet(referenceSyncToMPSRequired)) { + try { + if (tree.containsNode(roleInNode.getNodeId())) { + synchronizer.syncReferenceToMPS(roleInNode.getNodeId(), roleInNode.getRole(), tree); + } + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + SetSequence.fromSet(referenceSyncToMPSRequired).clear(); + + for (RoleInNode roleInNode : SetSequence.fromSet(propertySyncToMPSRequired)) { + try { + if (tree.containsNode(roleInNode.getNodeId())) { + synchronizer.syncPropertyToMPS(roleInNode.getNodeId(), roleInNode.getRole(), tree); + } + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + SetSequence.fromSet(propertySyncToMPSRequired).clear(); + + fullNodeSyncToMPSRequired.forEach(new TLongProcedure() { + public boolean execute(long nodeId) { + try { + if (tree.containsNode(nodeId)) { + synchronizer.syncNodeToMPS(nodeId, tree, true); + } + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + return true; + } + }); + fullNodeSyncToMPSRequired.clear(); + + if (modelPropertiesSyncToMPSRequired) { + try { + synchronizer.syncModelPropertiesToMPS(tree); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + } + }); + modelPropertiesSyncToMPSRequired = false; + } + } + + @Nullable + @Override + protected ITreeChangeVisitor getTreeChangeVisitor(final ITree oldTree, final ITree newTree) { + return new ITreeChangeVisitorEx() { + public boolean isInsideModel(long nodeId) { + assertSyncThread(); + long parent = newTree.getParent(nodeId); + if (parent == 0) { + return false; + } + if (parent == modelNodeId) { + return Objects.equals(newTree.getRole(nodeId), LINKS.rootNodes$jxXY.getName()); + } + return isInsideModel(parent); + } + public boolean isInsideModelOrModel(long nodeId) { + assertSyncThread(); + if (nodeId == modelNodeId) { + return true; + } + return isInsideModel(nodeId); + } + public boolean isModelProperties(long nodeId) { + assertSyncThread(); + long parent = newTree.getParent(nodeId); + if (parent == 0) { + return false; + } + if (parent == modelNodeId) { + return !(Objects.equals(newTree.getRole(nodeId), LINKS.rootNodes$jxXY.getName())); + } + return isModelProperties(parent); + } + + @Override + public void containmentChanged(long nodeId) { + } + + @Override + public void childrenChanged(final long nodeId, final String role) { + assertSyncThread(); + if (modelNodeId == nodeId) { + if (Objects.equals(role, LINKS.rootNodes$jxXY.getName())) { + SetSequence.fromSet(childrenSyncToMPSRequired).addElement(new RoleInNode(nodeId, role)); + } else { + modelPropertiesSyncToMPSRequired = true; + } + } else if (isModelProperties(nodeId)) { + modelPropertiesSyncToMPSRequired = true; + } else if (isInsideModel(nodeId)) { + SetSequence.fromSet(childrenSyncToMPSRequired).addElement(new RoleInNode(nodeId, role)); + } + enqueueSync(SyncDirection.TO_MPS, false, null); + } + + @Override + public void referenceChanged(long nodeId, String role) { + assertSyncThread(); + if (isModelProperties(nodeId)) { + modelPropertiesSyncToMPSRequired = true; + enqueueSync(SyncDirection.TO_MPS, false, null); + return; + } + if (!(isInsideModel(nodeId))) { + return; + } + SetSequence.fromSet(referenceSyncToMPSRequired).addElement(new RoleInNode(nodeId, role)); + enqueueSync(SyncDirection.TO_MPS, false, null); + } + + @Override + public void propertyChanged(final long nodeId, String role) { + assertSyncThread(); + if (isModelProperties(nodeId)) { + modelPropertiesSyncToMPSRequired = true; + enqueueSync(SyncDirection.TO_MPS, false, null); + return; + } + if (!(isInsideModel(nodeId))) { + return; + } + SetSequence.fromSet(propertySyncToMPSRequired).addElement(new RoleInNode(nodeId, role)); + enqueueSync(SyncDirection.TO_MPS, false, null); + } + + @Override + public void nodeRemoved(long nodeId) { + } + + @Override + public void nodeAdded(long nodeId) { + assertSyncThread(); + if (!(isInsideModel(nodeId))) { + return; + } + fullNodeSyncToMPSRequired.add(nodeId); + enqueueSync(SyncDirection.TO_MPS, false, null); + } + }; + } + + private static final class LINKS { + /*package*/ static final SContainmentLink rootNodes$jxXY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x69652614fd1c514L, "rootNodes"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelCloudExporter.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelCloudExporter.java new file mode 100644 index 00000000..16417120 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelCloudExporter.java @@ -0,0 +1,442 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.annotations.Nullable; +import org.modelix.model.lazy.RepositoryId; +import java.util.List; +import jetbrains.mps.project.Solution; +import jetbrains.mps.project.Project; +import java.util.Set; +import jetbrains.mps.ide.MPSCoreComponents; +import com.intellij.openapi.application.ApplicationManager; +import jetbrains.mps.vfs.VFSManager; +import jetbrains.mps.vfs.IFileSystem; +import jetbrains.mps.vfs.IFile; +import java.io.File; +import org.modelix.model.client.RestWebModelClient; +import org.modelix.model.lazy.CLVersion; +import kotlin.jvm.functions.Function0; +import org.modelix.model.lazy.CLTree; +import org.modelix.model.api.IBranch; +import org.modelix.model.metameta.MetaModelBranch; +import org.modelix.model.api.PBranch; +import org.modelix.model.api.IdGeneratorDummy; +import org.modelix.model.area.PArea; +import org.modelix.model.lazy.PrefetchCache; +import org.modelix.model.api.ITransaction; +import org.modelix.model.api.ITree; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import org.modelix.model.api.INode; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.modelix.model.api.PNodeAdapter; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.LinkedList; +import jetbrains.mps.project.MPSExtentions; +import com.intellij.openapi.vfs.VirtualFileManager; +import jetbrains.mps.project.structure.modules.SolutionDescriptor; +import jetbrains.mps.project.ModuleId; +import java.util.UUID; +import jetbrains.mps.persistence.DefaultModelRoot; +import jetbrains.mps.project.structure.modules.SolutionKind; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.jetbrains.mps.openapi.persistence.Memento; +import jetbrains.mps.persistence.MementoImpl; +import jetbrains.mps.project.structure.modules.ModuleFacetDescriptor; +import jetbrains.mps.project.facets.JavaModuleFacet; +import jetbrains.mps.smodel.GeneralModuleFactory; +import jetbrains.mps.persistence.LazyLoadFacility; +import jetbrains.mps.persistence.DefaultModelPersistence; +import org.jetbrains.mps.openapi.persistence.StreamDataSource; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.smodel.SModelHeader; +import jetbrains.mps.smodel.persistence.def.ModelReadException; +import jetbrains.mps.smodel.persistence.def.ModelPersistence; +import jetbrains.mps.smodel.loading.ModelLoadResult; +import jetbrains.mps.smodel.loading.ModelLoadingState; +import jetbrains.mps.extapi.model.SModelData; +import java.io.IOException; +import org.jetbrains.concurrency.AsyncPromise; +import jetbrains.mps.ide.ThreadUtils; +import jetbrains.mps.smodel.SModel; +import org.jetbrains.mps.openapi.persistence.ModelSaveException; +import jetbrains.mps.project.AbstractModule; +import java.util.Iterator; +import org.jetbrains.mps.openapi.persistence.ModelRoot; +import org.jetbrains.mps.openapi.model.SModelName; +import jetbrains.mps.smodel.SModelId; +import org.jetbrains.mps.openapi.persistence.ModelFactory; +import org.jetbrains.mps.openapi.persistence.DataSource; +import org.jetbrains.mps.openapi.persistence.ModelLoadingOption; +import org.jetbrains.mps.openapi.persistence.UnsupportedDataSourceException; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.mps.openapi.persistence.PersistenceFacade; +import jetbrains.mps.smodel.DefaultSModelDescriptor; +import jetbrains.mps.smodel.DefaultSModel; +import org.jetbrains.mps.openapi.model.EditableSModel; +import jetbrains.mps.persistence.ModelCannotBeCreatedException; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SConcept; + +public class ModelCloudExporter { + private static final String DEFAULT_BRANCH_NAME = "master"; + private static final String DEFAULT_URL = "http://localhost:28101/"; + private static final String DEFAULT_TREE_ID = "default"; + + private String branchName = DEFAULT_BRANCH_NAME; + private CloudRepository repositoryInModelServer; + + private boolean inCheckoutMode = false; + + public ModelCloudExporter setCheckoutMode() { + inCheckoutMode = true; + return this; + } + + public ModelCloudExporter(@Nullable String url, @Nullable String repositoryId, @Nullable String branchName) { + if ((url == null || url.length() == 0)) { + url = DEFAULT_URL; + } + if (!(url.endsWith("/"))) { + url += "/"; + } + if ((repositoryId == null || repositoryId.length() == 0)) { + repositoryId = DEFAULT_TREE_ID; + } + ModelServerConnection modelServer = ModelServerConnections.getInstance().getModelServer(url); + if (modelServer == null) { + throw new IllegalStateException("No ModelServer connection found for url " + url); + } + this.repositoryInModelServer = new CloudRepository(modelServer, new RepositoryId(repositoryId)); + if ((branchName != null && branchName.length() > 0)) { + this.branchName = branchName; + } else { + this.branchName = DEFAULT_BRANCH_NAME; + } + } + + public ModelCloudExporter(CloudRepository treeInRepository, @Nullable String branchName) { + this.repositoryInModelServer = treeInRepository; + if (branchName == null) { + this.branchName = DEFAULT_BRANCH_NAME; + } else { + this.branchName = branchName; + } + } + + public ModelCloudExporter(CloudRepository treeInRepository) { + this(treeInRepository, treeInRepository.getActiveBranch().getBranchName()); + } + + public List export(String exportPath, Project mpsProject) { + return export(exportPath, null, mpsProject); + } + + /** + * + * + * @param exportPath + * @param selectedMduleIds null indicates all modules + * @param mpsProject + * @return + */ + public List export(String exportPath, @Nullable Set selectedMduleIds, @Nullable Project mpsProject) { + MPSCoreComponents coreComponents = ApplicationManager.getApplication().getComponent(MPSCoreComponents.class); + VFSManager vfsManager = coreComponents.getPlatform().findComponent(VFSManager.class); + IFileSystem fileSystem = vfsManager.getFileSystem(VFSManager.FILE_FS); + IFile outputFolder = fileSystem.getFile(new File(exportPath)); + return export(outputFolder, selectedMduleIds, mpsProject); + } + + public List export(IFile outputFolder, Project mpsProject) { + return export(outputFolder, null, mpsProject); + } + + /** + * This method is expected to be called when a user is present to see the notifications. + * + * @param outputFolder + * @param selectedModuleIds null indicates all modules + * @param mpsProject + * @return + */ + public List export(final IFile outputFolder, @Nullable final Set selectedModuleIds, final Project mpsProject) { + System.out.println("exporting to " + outputFolder.getPath()); + System.out.println("the output folder exists? " + outputFolder.exists()); + + if (!(inCheckoutMode)) { + outputFolder.deleteIfExists(); + } + + String url = repositoryInModelServer.getModelServer().getBaseUrl(); + RestWebModelClient client = new RestWebModelClient(url); + RepositoryId repositoryId = repositoryInModelServer.getRepositoryId(); + String branchKey = repositoryId.getBranchKey(branchName); + String versionHash = null; + try { + versionHash = client.get(branchKey); + } catch (Exception e) { + throw new RuntimeException("Issue retrieving key " + branchKey + " with base URL " + client.getBaseUrl(), e); + } + if ((versionHash == null || versionHash.length() == 0)) { + throw new RuntimeException("No version found at " + url + "get/" + branchKey + ". Base URL " + client.getBaseUrl()); + } + final CLVersion version = CLVersion.Companion.loadFromHash(versionHash, client.getStoreCache()); + if (version == null) { + throw new RuntimeException("Branch " + branchKey + " references non-existent version " + versionHash); + } + return repositoryInModelServer.computeRead(new Function0>() { + public List invoke() { + final CLTree tree = version.getTree(); + final IBranch branch = new MetaModelBranch(new PBranch(tree, new IdGeneratorDummy())); + return new PArea(branch).executeRead(new Function0>() { + public List invoke() { + return PrefetchCache.Companion.with(tree, new Function0>() { + public List invoke() { + ITransaction t = branch.getTransaction(); + Iterable moduleIds = t.getChildren(ITree.ROOT_ID, LINKS.modules$jBPn.getName()); + if (moduleIds != null && selectedModuleIds != null) { + moduleIds = Sequence.fromIterable(moduleIds).intersect(SetSequence.fromSet(selectedModuleIds)); + } + + // prefetch module contents + tree.getDescendants(moduleIds, true); + + List modules = Sequence.fromIterable(moduleIds).select(new ISelector() { + public INode select(Long it) { + INode n = new PNodeAdapter(it, branch); + return n; + } + }).toListSequence(); + return createModules(modules, outputFolder, mpsProject); + } + }); + } + }); + } + }); + } + + /** + * This method is expected to be called when a user is present to see the notifications. + */ + private List createModules(List modules, IFile outputFolder, Project mpsProject) { + List solutions = ListSequence.fromList(new LinkedList()); + for (INode module : modules) { + Solution s = createModule(module, outputFolder, mpsProject); + if (s != null) { + ListSequence.fromList(solutions).addElement(s); + } + } + return solutions; + } + + /** + * We experienced issues with physical and virtual files being out of sync. + * This method ensure that files are deleted, recursively both on the virtual filesystem and the physical filesystem + */ + private void ensureDeletion(IFile virtualFile) { + if (virtualFile.isDirectory()) { + for (IFile child : ListSequence.fromList(virtualFile.getChildren())) { + ensureDeletion(child); + } + } else { + if (virtualFile.exists()) { + virtualFile.delete(); + } + File physicalFile = new File(virtualFile.getPath()); + physicalFile.delete(); + } + } + + private void ensureDirDeletionAndRecreation(IFile virtualDir) { + ensureDeletion(virtualDir); + virtualDir.mkdirs(); + } + + /** + * This method is expected to be called when a user is present to see the notification. + */ + private Solution createModule(INode module, IFile outputFolder, Project mpsProject) { + String name = module.getPropertyValue("name"); + String moduleIdAsString = module.getPropertyValue("id"); + if (moduleIdAsString == null) { + ModelixNotifications.notifyError("Module without ID", "Module " + name + " has been stored without an ID. Please set the ID and check it out again"); + return null; + } + + MPSCoreComponents coreComponents = ApplicationManager.getApplication().getComponent(MPSCoreComponents.class); + VFSManager vfsManager = coreComponents.getPlatform().findComponent(VFSManager.class); + IFileSystem fileSystem = vfsManager.getFileSystem(VFSManager.FILE_FS); + if (!(inCheckoutMode)) { + outputFolder.deleteIfExists(); + } + IFile solutionFile = outputFolder.findChild(name).findChild("solution" + MPSExtentions.DOT_SOLUTION); + final IFile solutionDir = outputFolder.findChild(name); + if (inCheckoutMode) { + ApplicationManager.getApplication().invokeAndWait(new Runnable() { + @Override + public void run() { + VirtualFileManager.getInstance().syncRefresh(); + IFile modelsDirVirtual = solutionDir.findChild("models"); + ensureDirDeletionAndRecreation(modelsDirVirtual); + } + }); + } + SolutionDescriptor descriptor = new SolutionDescriptor(); + descriptor.setNamespace(name); + ModuleId solutionId = ModuleId.regular(UUID.fromString(moduleIdAsString)); + descriptor.setId(solutionId); + descriptor.getModelRootDescriptors().add(DefaultModelRoot.createDescriptor(solutionFile.getParent(), solutionFile.getParent().findChild(Solution.SOLUTION_MODELS))); + descriptor.setKind(SolutionKind.PLUGIN_OTHER); + + for (INode facet : Sequence.fromIterable(module.getChildren("facets"))) { + if (facet.getConcept().isSubConceptOf(SConceptAdapter.wrap(CONCEPTS.JavaModuleFacet$5E))) { + Memento javaFacetMemento = new MementoImpl(); + Memento javaFacetClassesMemento = javaFacetMemento.createChild("classes"); + javaFacetClassesMemento.put("generated", facet.getPropertyValue("generated")); + javaFacetClassesMemento.put("path", facet.getPropertyValue("path").replaceAll("\\$\\{module\\}", solutionFile.getParent().toRealPath())); + ModuleFacetDescriptor javaFacetDescriptor = new ModuleFacetDescriptor(JavaModuleFacet.FACET_TYPE, javaFacetMemento); + descriptor.getModuleFacetDescriptors().add(javaFacetDescriptor); + } + } + + Solution solution = (Solution) new GeneralModuleFactory().instantiate(descriptor, solutionFile); + if (mpsProject != null) { + mpsProject.addModule(solution); + if (solution.getRepository() == null) { + solution.attach(mpsProject.getRepository()); + } + } + if (mpsProject != null && solution.getRepository() == null) { + throw new IllegalStateException("The solution should be in a repo, so also the model will be in a repo and syncReference will not crash"); + } + for (INode model : module.getChildren("models")) { + createModel(solution, model); + } + solution.save(); + + return solution; + } + + /** + * We had to copy it from https://github.com/JetBrains/MPS/blob/14b86a2f987cdd3fbcc72b9262e8b388f7a5fae3/core/persistence/source/jetbrains/mps/persistence/DefaultModelPersistence.java#L115 + */ + private static class PersistenceFacility extends LazyLoadFacility { + /*package*/ PersistenceFacility(DefaultModelPersistence modelFactory, StreamDataSource dataSource) { + super(modelFactory, dataSource, true); + } + @NotNull + private StreamDataSource getSource0() { + return (StreamDataSource) super.getSource(); + } + @NotNull + @Override + public SModelHeader readHeader() throws ModelReadException { + return ModelPersistence.loadDescriptor(getSource0()); + } + @NotNull + @Override + public ModelLoadResult readModel(@NotNull SModelHeader header, @NotNull ModelLoadingState state) throws ModelReadException { + return ModelPersistence.readModel(header, getSource0(), state); + } + @Override + public boolean doesSaveUpgradePersistence(@NotNull SModelHeader header) { + // not sure !=-1 is really needed, just left to be ensured about compatibility + return header.getPersistenceVersion() != ModelPersistence.LAST_VERSION && header.getPersistenceVersion() != -1; + } + @Override + public void saveModel(@NotNull final SModelHeader header, final SModelData modelData) throws IOException { + final AsyncPromise res = new AsyncPromise(); + ThreadUtils.runInUIThreadNoWait(new Runnable() { + public void run() { + try { + ModelPersistence.saveModel((SModel) modelData, getSource0(), header.getPersistenceVersion()); + res.setResult(true); + } catch (ModelSaveException e) { + e.printStackTrace(); + res.setResult(false); + } + } + }); + if (!(res.get())) { + throw new RuntimeException("Unable to save model"); + } + } + } + + private void createModel(AbstractModule module, INode model) { + Iterator modelRootsIt = module.getModelRoots().iterator(); + if (!(modelRootsIt.hasNext())) { + throw new IllegalStateException("Module has not default model root: " + module + " (" + module.getModuleName() + ")"); + } + final DefaultModelRoot defaultModelRoot = ((DefaultModelRoot) modelRootsIt.next()); + final SModelName sModelName = new SModelName(model.getPropertyValue("name")); + final SModelId imposedModelID = SModelId.fromString(model.getPropertyValue("id")); + final ModelFactory modelFactory = new ModelPersistenceWithFixedId(module.getModuleReference(), imposedModelID) { + @NotNull + @Override + public org.jetbrains.mps.openapi.model.SModel create(@NotNull DataSource dataSource, @NotNull SModelName modelName, @NotNull ModelLoadingOption... options) throws UnsupportedDataSourceException { + // COPIED FROM https://github.com/JetBrains/MPS/blob/14b86a2f987cdd3fbcc72b9262e8b388f7a5fae3/core/persistence/source/jetbrains/mps/persistence/DefaultModelPersistence.java#L115 + + if (!((supports(dataSource)))) { + throw new UnsupportedDataSourceException(dataSource); + } + final SModelHeader header = SModelHeader.create(ModelPersistence.LAST_VERSION); + final SModelReference modelReference = PersistenceFacade.getInstance().createModelReference(null, imposedModelID, modelName.getValue()); + header.setModelReference(modelReference); + final DefaultSModelDescriptor rv = new DefaultSModelDescriptor(new PersistenceFacility(this, (StreamDataSource) dataSource), header); + // Hack to ensure newly created model is indeed empty. Otherwise, with StreamDataSource pointing to existing model stream, an attempt to + // do anything with the model triggers loading and the model get all the data. Two approaches deemed reasonable to tackle the issue: + // (a) enforce clear empty model (why would anyone call #create() then) + // (b) fail with error (too brutal?) + // Another alternative considered is to tolerate any DataSource in DefaultSModelDescriptor (or its persistence counterpart), so that + // one can create an empty model with NullDataSource, and later save with a proper DataSource (which yields more job to client and makes him + // question why SModel.save() is there). This task is reasonable regardless of final approach taken, but would take more effort, hence the hack. + if (dataSource.getTimestamp() != -1) { + // chances are there's something in the stream already + rv.replace(new DefaultSModel(modelReference, header)); + // model state is FULLY_LOADED, DataSource won't get read + } + return rv; + } + }; + // We create models asynchronously, similarly to what is done in mpsutil.smodule + // this helps avoiding issues with VFS and physical FS being out of sync + VirtualFileManager.getInstance().syncRefresh(); + final AsyncPromise res = new AsyncPromise(); + ThreadUtils.runInUIThreadNoWait(new Runnable() { + public void run() { + try { + System.out.println("creating model " + sModelName); + EditableSModel smodel = (EditableSModel) defaultModelRoot.createModel(sModelName, null, null, modelFactory); + System.out.println(" model " + sModelName + " created"); + res.setResult(smodel); + } catch (ModelCannotBeCreatedException e) { + res.setResult(null); + throw new RuntimeException(e); + } + } + }); + final EditableSModel smodel = res.get(); + if (smodel != null) { + new ModelSynchronizer(((PNodeAdapter) model).getNodeId(), smodel, repositoryInModelServer).syncModelToMPS(((PNodeAdapter) model).getBranch().getTransaction().getTree(), true); + module.getRepository().getModelAccess().runWriteAction(new Runnable() { + public void run() { + smodel.save(); + System.out.println(" model " + sModelName + " saved"); + } + }); + } + } + + private static final class LINKS { + /*package*/ static final SContainmentLink modules$jBPn = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x69652614fd1c517L, "modules"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept JavaModuleFacet$5E = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde9535299166L, "org.modelix.model.repositoryconcepts.structure.JavaModuleFacet"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelCloudImportUtils.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelCloudImportUtils.java new file mode 100644 index 00000000..638c8a31 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelCloudImportUtils.java @@ -0,0 +1,245 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import javax.swing.tree.TreeNode; +import jetbrains.mps.project.Project; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNodeBinding; +import org.modelix.model.api.PNodeAdapter; +import jetbrains.mps.project.Solution; +import jetbrains.mps.ide.project.ProjectHelper; +import org.modelix.model.mpsplugin.plugin.PersistedBindingConfiguration; +import jetbrains.mps.project.MPSProject; +import org.modelix.model.lazy.RepositoryId; +import org.jetbrains.mps.openapi.module.SModule; +import org.modelix.model.api.INode; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.util.ProgressMonitor; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.mpsadapters.mps.NodeToSNodeAdapter; +import java.util.function.Consumer; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import jetbrains.mps.progress.EmptyProgressMonitor; +import org.modelix.model.mpsadapters.mps.SModuleAsNode; +import java.util.List; +import org.jetbrains.mps.openapi.model.SModel; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.modelix.model.mpsadapters.mps.SModelAsNode; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.model.SReference; +import org.modelix.model.mpsadapters.mps.SNodeToNodeAdapter; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SConcept; + +/** + * This class is responsible for importing local MPS modules into the Modelix server + */ +public class ModelCloudImportUtils { + + public static void checkoutAndSync(TreeNode treeNode, final Project mpsProject) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) treeNode; + final CloudRepository treeInRepository = CloudNodeTreeNodeBinding.getTreeInRepository(nodeTreeNode); + final PNodeAdapter cloudModuleNode = ((PNodeAdapter) nodeTreeNode.getNode()); + final Solution solution = new ModuleCheckout(mpsProject, treeInRepository).checkoutCloudModule(cloudModuleNode); + mpsProject.getRepository().getModelAccess().runReadAction(new Runnable() { + public void run() { + syncInModelixAsIndependentModule(treeInRepository, solution, ProjectHelper.toIdeaProject(mpsProject), cloudModuleNode); + } + }); + PersistedBindingConfiguration.getInstance(ProjectHelper.toIdeaProject(mpsProject)).addMappedBoundModule(treeInRepository, cloudModuleNode); + } + + public static void checkoutAndSync(final CloudRepository treeInRepository, final Project mpsProject, long cloudModuleNodeId) { + final PNodeAdapter cloudModuleNode = new PNodeAdapter(cloudModuleNodeId, treeInRepository.getActiveBranch().getBranch()); + final Solution solution = new ModuleCheckout(mpsProject, treeInRepository).checkoutCloudModule(cloudModuleNode); + mpsProject.getRepository().getModelAccess().runReadAction(new Runnable() { + public void run() { + syncInModelixAsIndependentModule(treeInRepository, solution, ProjectHelper.toIdeaProject(mpsProject), cloudModuleNode); + } + }); + PersistedBindingConfiguration.getInstance(ProjectHelper.toIdeaProject(mpsProject)).addMappedBoundModule(treeInRepository, cloudModuleNode); + } + + public static void bindCloudProjectToMpsProject(CloudRepository repositoryInModelServer, long cloudProjectId, MPSProject mpsProject, SyncDirection initialSyncDirection) { + repositoryInModelServer.addBinding(new ProjectBinding(mpsProject, cloudProjectId, initialSyncDirection)); + } + + public static TransientModuleBinding addTransientModuleBinding(com.intellij.openapi.project.Project mpsProject, CloudRepository repositoryInModelServer, long cloudNodeId) { + ModelServerConnection modelServerConnection = repositoryInModelServer.getModelServer(); + RepositoryId repositoryId = repositoryInModelServer.getRepositoryId(); + TransientModuleBinding transientModuleBinding = new TransientModuleBinding(cloudNodeId); + modelServerConnection.addBinding(repositoryId, transientModuleBinding); + PersistedBindingConfiguration.getInstance(mpsProject).addTransientBoundModule(repositoryInModelServer, repositoryInModelServer.getActiveBranch().getBranch(), cloudNodeId); + return transientModuleBinding; + } + public static boolean containsModule(CloudRepository treeInRepository, SModule module) { + return treeInRepository.hasModuleInRepository(module.getModuleId().toString()); + } + + /** + * We create an exact copy of a physical module into Modelix, as a root level module + * (i.e., a module right below a Tree) + */ + public static INode copyInModelixAsIndependentModule(final CloudRepository treeInRepository, final SModule module, com.intellij.openapi.project.Project project, @Nullable ProgressMonitor progress) { + // First create the module + final INode cloudModuleNode = treeInRepository.createModule(module.getModuleName()); + replicatePhysicalModule(treeInRepository, cloudModuleNode, module, null, progress); + return cloudModuleNode; + } + + public static void copyAndSyncInModelixAsIndependentModule(CloudRepository treeInRepository, SModule module, com.intellij.openapi.project.Project mpsProject, @Nullable ProgressMonitor progress) { + + // 1. Copy the module in the cloud repo + INode cloudModuleNode = copyInModelixAsIndependentModule(treeInRepository, module, mpsProject, progress); + + syncInModelixAsIndependentModule(treeInRepository, module, mpsProject, cloudModuleNode); + } + + public static ProjectBinding copyAndSyncInModelixAsEntireProject(CloudRepository treeInRepository, MPSProject mpsProject, SNode cloudProject) { + ProjectBinding binding; + if (cloudProject == null) { + binding = treeInRepository.addProjectBinding(0L, mpsProject, SyncDirection.TO_CLOUD); + PersistedBindingConfiguration.getInstance(ProjectHelper.toIdeaProject(mpsProject)).addTransientBoundProject(treeInRepository, cloudProject); + } else { + NodeToSNodeAdapter cloudProjectAsNodeToSNodeAdapter = (NodeToSNodeAdapter) ((Object) cloudProject); + INode cloudProjectAsINode = cloudProjectAsNodeToSNodeAdapter.getWrapped(); + long nodeId = INodeUtils.nodeIdAsLong(cloudProjectAsINode); + binding = treeInRepository.addProjectBinding(nodeId, mpsProject, SyncDirection.TO_MPS); + PersistedBindingConfiguration.getInstance(ProjectHelper.toIdeaProject(mpsProject)).addTransientBoundProject(treeInRepository, cloudProject); + } + return binding; + } + + + public static void syncInModelixAsIndependentModule(CloudRepository treeInRepository, SModule module, com.intellij.openapi.project.Project mpsProject, INode cloudModuleNode) { + + ModelServerConnection msc = treeInRepository.getModelServer(); + msc.addBinding(treeInRepository.getRepositoryId(), new ProjectModuleBinding(((PNodeAdapter) cloudModuleNode).getNodeId(), module, SyncDirection.TO_MPS)); + + PersistedBindingConfiguration.getInstance(mpsProject).addMappedBoundModule(treeInRepository, ((PNodeAdapter) cloudModuleNode)); + } + + /** + * Take an INode already created and make sure it is exactly the same as the physical module given. + * The modelMappingConsumer may be used to attach a model synchronizer, for example. It is optional. + */ + public static void replicatePhysicalModule(final CloudRepository treeInRepository, final INode cloudModule, final SModule physicalModule, final Consumer modelMappingConsumer, @Nullable ProgressMonitor progress) { + final Wrappers._T _progress = new Wrappers._T(progress); + if (_progress.value == null) { + _progress.value = new EmptyProgressMonitor(); + } + + final SModuleAsNode sModuleAsNode = SModuleAsNode.wrap(physicalModule); + + treeInRepository.runWrite(new Consumer() { + public void accept(PNodeAdapter rootNode) { + INodeUtils.copyProperty(cloudModule, sModuleAsNode, PROPS.name$MnvL.getName()); + INodeUtils.copyProperty(cloudModule, sModuleAsNode, PROPS.id$7MjP.getName()); + INodeUtils.copyProperty(cloudModule, sModuleAsNode, PROPS.moduleVersion$sDQK.getName()); + INodeUtils.copyProperty(cloudModule, sModuleAsNode, PROPS.compileInMPS$sEzN.getName()); + + INodeUtils.cloneChildren(cloudModule, sModuleAsNode, LINKS.facets$vw9T.getName()); + INodeUtils.cloneChildren(cloudModule, sModuleAsNode, LINKS.dependencies$vC8r.getName()); + INodeUtils.cloneChildren(cloudModule, sModuleAsNode, LINKS.languageDependencies$vKlY.getName()); + } + }); + + + final Wrappers._T> models = new Wrappers._T>(null); + physicalModule.getRepository().getModelAccess().runReadAction(new Runnable() { + public void run() { + models.value = ListSequence.fromListWithValues(new ArrayList(), SModuleUtils.getModelsWithoutDescriptor(physicalModule)); + } + }); + _progress.value.start("Module " + physicalModule.getModuleName(), ListSequence.fromList(models.value).count()); + for (final SModel model : ListSequence.fromList(models.value)) { + if (_progress.value.isCanceled()) { + break; + } + physicalModule.getRepository().getModelAccess().runReadAction(new Runnable() { + public void run() { + ProgressMonitor modelProgress = _progress.value.subTask(1); + modelProgress.start("Model " + model.getName(), 1); + INode cloudModel = copyPhysicalModel(treeInRepository, cloudModule, model); + if (modelMappingConsumer != null) { + modelMappingConsumer.accept(new PhysicalToCloudModelMapping(model, cloudModel)); + } + modelProgress.done(); + } + }); + } + _progress.value.done(); + } + + /** + * This creates a copy of the given physicalModel under the given cloudModule. It then ensures that it is exactly the same as the given physicalModule. + * + * @return the created cloud model + */ + public static INode copyPhysicalModel(CloudRepository treeInRepository, INode cloudModule, final SModel physicalModel) { + final INode originalModel = SModelAsNode.wrap(physicalModel); + + INode cloudModel = treeInRepository.createNode(cloudModule, LINKS.models$h3QT, CONCEPTS.Model$2P, new Consumer() { + public void accept(INode cloudModel) { + INodeUtils.copyProperty(cloudModel, originalModel, PROPS.name$MnvL.getName()); + INodeUtils.copyProperty(cloudModel, originalModel, PROPS.id$lDUo.getName()); + + INodeUtils.cloneChildren(cloudModel, originalModel, LINKS.modelImports$8DOI.getName()); + INodeUtils.cloneChildren(cloudModel, originalModel, LINKS.usedLanguages$QK4E.getName()); + + for (SNode physicalRoot : Sequence.fromIterable(physicalModel.getRootNodes())) { + INode cloudRoot = cloudModel.addNewChild(LINKS.rootNodes$jxXY.getName(), -1, SConceptAdapter.wrap(physicalRoot.getConcept())); + replicatePhysicalNode(cloudRoot, physicalRoot); + } + } + }); + return cloudModel; + } + + /** + * This takes a cloud node already created and a physical node. + * It then ensures that the cloud node is exactly as the original physical node. + * + * It operates recursively on children. + */ + private static void replicatePhysicalNode(INode cloudNode, SNode physicalNode) { + MPSNodeMapping.mapToMpsNode(cloudNode, physicalNode); + for (SProperty prop : Sequence.fromIterable(physicalNode.getProperties())) { + cloudNode.setPropertyValue(prop.getName(), physicalNode.getProperty(prop)); + } + for (SReference ref : Sequence.fromIterable(physicalNode.getReferences())) { + cloudNode.setReferenceTarget(ref.getRole(), SNodeToNodeAdapter.wrap(ref.getTargetNode())); + } + for (SNode physicalChild : Sequence.fromIterable(physicalNode.getChildren())) { + INode cloudChild = cloudNode.addNewChild(physicalChild.getContainmentLink().getName(), -1, SConceptAdapter.wrap(physicalChild.getConcept())); + replicatePhysicalNode(cloudChild, physicalChild); + } + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$7MjP = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x3aa34013f2a802e0L, "id"); + /*package*/ static final SProperty moduleVersion$sDQK = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299142L, "moduleVersion"); + /*package*/ static final SProperty compileInMPS$sEzN = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299145L, "compileInMPS"); + /*package*/ static final SProperty id$lDUo = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x244b85440ee67212L, "id"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink facets$vw9T = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde953529916cL, "facets"); + /*package*/ static final SContainmentLink dependencies$vC8r = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299179L, "dependencies"); + /*package*/ static final SContainmentLink languageDependencies$vKlY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x1e9fde9535299187L, "languageDependencies"); + /*package*/ static final SContainmentLink models$h3QT = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x69652614fd1c512L, "models"); + /*package*/ static final SContainmentLink modelImports$8DOI = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x58dbe6e4d4f32eb8L, "modelImports"); + /*package*/ static final SContainmentLink usedLanguages$QK4E = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x4aaf28cf2092e98eL, "usedLanguages"); + /*package*/ static final SContainmentLink rootNodes$jxXY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x69652614fd1c514L, "rootNodes"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Model$2P = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, "org.modelix.model.repositoryconcepts.structure.Model"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelPersistenceWithFixedId.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelPersistenceWithFixedId.java new file mode 100644 index 00000000..d51be0db --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelPersistenceWithFixedId.java @@ -0,0 +1,91 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import jetbrains.mps.persistence.DefaultModelPersistence; +import org.jetbrains.mps.openapi.module.SModuleReference; +import org.jetbrains.mps.openapi.model.SModelId; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.persistence.DataSource; +import org.jetbrains.mps.openapi.model.SModelName; +import org.jetbrains.mps.openapi.persistence.ModelLoadingOption; +import org.jetbrains.mps.openapi.persistence.UnsupportedDataSourceException; +import jetbrains.mps.smodel.SModelHeader; +import jetbrains.mps.smodel.persistence.def.ModelPersistence; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.jetbrains.mps.openapi.persistence.PersistenceFacade; +import jetbrains.mps.smodel.DefaultSModelDescriptor; +import org.jetbrains.mps.openapi.persistence.StreamDataSource; +import jetbrains.mps.smodel.DefaultSModel; +import jetbrains.mps.persistence.LazyLoadFacility; +import jetbrains.mps.smodel.persistence.def.ModelReadException; +import jetbrains.mps.smodel.loading.ModelLoadResult; +import jetbrains.mps.smodel.loading.ModelLoadingState; +import jetbrains.mps.extapi.model.SModelData; +import java.io.IOException; +import org.jetbrains.mps.openapi.persistence.ModelSaveException; + +/** + * Uses the provided model ID instead of SModelId.generate(). + * Everything else is just copied from DefaultModelPersistence. + */ +public class ModelPersistenceWithFixedId extends DefaultModelPersistence { + private SModuleReference moduleRef; + private SModelId modelId; + + public ModelPersistenceWithFixedId(SModuleReference moduleRef, SModelId modelId) { + this.moduleRef = moduleRef; + this.modelId = modelId; + } + + @NotNull + @Override + public SModel create(@NotNull DataSource dataSource, @NotNull SModelName modelName, @NotNull ModelLoadingOption... options) throws UnsupportedDataSourceException { + if (!((supports(dataSource)))) { + throw new UnsupportedDataSourceException(dataSource); + } + final SModelHeader header = SModelHeader.create(ModelPersistence.LAST_VERSION); + final SModelReference modelReference = PersistenceFacade.getInstance().createModelReference(moduleRef, modelId, modelName.getValue()); + header.setModelReference(modelReference); + final DefaultSModelDescriptor rv = new DefaultSModelDescriptor(new PersistenceFacility(this, (StreamDataSource) dataSource), header); + if (dataSource.getTimestamp() != -1) { + rv.replace(new DefaultSModel(modelReference, header)); + } + return rv; + } + + private static class PersistenceFacility extends LazyLoadFacility { + public PersistenceFacility(DefaultModelPersistence modelFactory, StreamDataSource dataSource) { + super(modelFactory, dataSource, true); + } + @NotNull + private StreamDataSource getSource0() { + return (StreamDataSource) super.getSource(); + } + @NotNull + @Override + public SModelHeader readHeader() throws ModelReadException { + return ModelPersistence.loadDescriptor(getSource0()); + } + @NotNull + @Override + public ModelLoadResult readModel(@NotNull SModelHeader header, @NotNull ModelLoadingState state) throws ModelReadException { + return ModelPersistence.readModel(header, getSource0(), state); + } + @Override + public boolean doesSaveUpgradePersistence(@NotNull SModelHeader header) { + // not sure !=-1 is really needed, just left to be ensured about compatibility + return header.getPersistenceVersion() != ModelPersistence.LAST_VERSION && header.getPersistenceVersion() != -1; + } + @Override + public void saveModel(@NotNull SModelHeader header, SModelData modelData) throws IOException { + try { + ModelPersistence.saveModel((jetbrains.mps.smodel.SModel) modelData, getSource0(), header.getPersistenceVersion()); + } catch (ModelSaveException e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelPropertiesSynchronizer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelPropertiesSynchronizer.java new file mode 100644 index 00000000..44f72dbf --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelPropertiesSynchronizer.java @@ -0,0 +1,415 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.jetbrains.mps.openapi.model.SModel; +import org.modelix.model.api.IBranch; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.modelix.model.api.ITree; +import java.util.List; +import jetbrains.mps.project.Project; +import jetbrains.mps.project.ProjectManager; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.lang.migration.runtime.base.VersionFixer; +import org.apache.log4j.Level; +import org.modelix.model.mpsadapters.mps.SModelAsNode; +import org.modelix.model.api.INode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.mpsadapters.mps.DevKitDependencyAsNode; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import java.util.Objects; +import org.modelix.model.mpsadapters.mps.SingleLanguageDependencyAsNode; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.project.DevKit; +import jetbrains.mps.project.ModuleId; +import java.util.UUID; +import org.jetbrains.mps.openapi.module.SModuleReference; +import jetbrains.mps.smodel.Language; +import org.jetbrains.mps.openapi.language.SLanguage; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import jetbrains.mps.smodel.DefaultSModelDescriptor; +import de.slisson.mps.reflection.runtime.ReflectionUtil; +import org.modelix.model.mpsadapters.mps.ModelImportAsNode; +import jetbrains.mps.project.structure.modules.ModuleReference; +import org.jetbrains.mps.openapi.model.SModelId; +import jetbrains.mps.smodel.SModelReference; +import jetbrains.mps.smodel.ModelImports; +import jetbrains.mps.extapi.model.SModelDescriptorStub; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SConcept; + +/*package*/ class ModelPropertiesSynchronizer { + private static final Logger LOG = LogManager.getLogger(ModelPropertiesSynchronizer.class); + protected SModel model; + protected long modelNodeId; + private ICloudRepository cloudRepository; + + public ModelPropertiesSynchronizer(long modelNodeId, SModel model, ICloudRepository cloudRepository) { + this.model = model; + this.modelNodeId = modelNodeId; + this.cloudRepository = cloudRepository; + } + + private IBranch getBranch() { + return cloudRepository.getBranch(); + } + + public void syncModelPropertiesFromMPS() { + new PArea(getBranch()).executeWrite(new Function0() { + public Unit invoke() { + syncUsedLanguagesAndDevKitsFromMPS(); + syncModelImportsFromMPS(); + return Unit.INSTANCE; + } + }); + } + + public void syncModelPropertiesToMPS(ITree tree, ICloudRepository cloudRepository) { + syncModelPropertiesToMPS(tree, model, modelNodeId, cloudRepository); + } + + /*package*/ static void syncModelPropertiesToMPS(ITree tree, SModel model, long modelNodeId, ICloudRepository cloudRepository) { + syncUsedLanguagesAndDevKitsToMPS(tree, model, modelNodeId, cloudRepository); + syncModelImportsToMPS(tree, model, modelNodeId, cloudRepository); + + try { + List projects = ProjectManager.getInstance().getOpenedProjects(); + if (ListSequence.fromList(projects).isNotEmpty()) { + new VersionFixer(ListSequence.fromList(projects).first(), model.getModule(), true).updateImportVersions(); + } + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to update language version after change in model " + model.getName().getValue(), ex); + } + } + } + + public void syncUsedLanguagesAndDevKitsFromMPS() { + new PArea(getBranch()).executeWrite(new Function0() { + public Unit invoke() { + // First get the dependencies in MPS + SModelAsNode mpsModelNode = SModelAsNode.wrap(model); + List dependenciesInMPS = IterableOfINodeUtils.toList(mpsModelNode.getChildren(LINKS.usedLanguages$QK4E.getName())); + + // Then get the dependencies in the cloud + IBranch branch = getBranch(); + INode cloudModelNode = new PNodeAdapter(modelNodeId, branch); + Iterable dependenciesInCloud = cloudModelNode.getChildren(LINKS.usedLanguages$QK4E.getName()); + + // For each import in MPS, add it if not present in the cloud, or otherwise ensure all properties are the same + for (final INode dependencyInMPS : ListSequence.fromList(dependenciesInMPS)) { + if (dependencyInMPS instanceof DevKitDependencyAsNode) { + INode matchingDependencyInCloud = Sequence.fromIterable(dependenciesInCloud).findFirst(new IWhereFilter() { + public boolean accept(INode dependencyInCloud) { + return Objects.equals(dependencyInMPS.getPropertyValue(PROPS.uuid$lpJp.getName()), dependencyInCloud.getPropertyValue(PROPS.uuid$lpJp.getName())); + } + }); + if (matchingDependencyInCloud == null) { + INodeUtils.replicateChild(cloudModelNode, LINKS.usedLanguages$QK4E.getName(), dependencyInMPS); + } else { + INodeUtils.copyProperty(cloudModelNode, dependencyInMPS, PROPS.name$lpYq); + } + } else if (dependencyInMPS instanceof SingleLanguageDependencyAsNode) { + INode matchingDependencyInCloud = Sequence.fromIterable(dependenciesInCloud).findFirst(new IWhereFilter() { + public boolean accept(INode dependencyInCloud) { + return Objects.equals(dependencyInMPS.getPropertyValue(PROPS.uuid$lpJp.getName()), dependencyInCloud.getPropertyValue(PROPS.uuid$lpJp.getName())); + } + }); + if (matchingDependencyInCloud == null) { + INodeUtils.replicateChild(cloudModelNode, LINKS.usedLanguages$QK4E.getName(), dependencyInMPS); + } else { + INodeUtils.copyProperty(cloudModelNode, dependencyInMPS, PROPS.name$lpYq); + INodeUtils.copyProperty(cloudModelNode, dependencyInMPS, PROPS.version$ApUL); + } + } else { + throw new RuntimeException("Unknown dependency type: " + dependencyInMPS.getClass().getName()); + } + } + + // For each import not in MPS, remove it + for (final INode dependencyInCloud : Sequence.fromIterable(dependenciesInCloud)) { + INode matchingDependencyInMPS = Sequence.fromIterable(dependenciesInCloud).findFirst(new IWhereFilter() { + public boolean accept(INode dependencyInMPS) { + return Objects.equals(dependencyInCloud.getPropertyValue(PROPS.uuid$lpJp.getName()), dependencyInMPS.getPropertyValue(PROPS.uuid$lpJp.getName())); + } + }); + if (matchingDependencyInMPS == null) { + cloudModelNode.removeChild(dependencyInCloud); + } + } + return Unit.INSTANCE; + } + }); + } + + + public static void syncUsedLanguagesAndDevKitsToMPS(ITree tree, final SModel model, final long modelNodeId, final ICloudRepository cloudRepository) { + new PArea(cloudRepository.getBranch()).executeRead(new Function0() { + public Unit invoke() { + ModelAccess.runInWriteActionIfNeeded(model, new Runnable() { + @Override + public void run() { + // First get the dependencies in MPS + SModelAsNode mpsModelNode = SModelAsNode.wrap(model); + List dependenciesInMPS = IterableOfINodeUtils.toList(mpsModelNode.getChildren(LINKS.usedLanguages$QK4E.getName())); + + // Then get the dependencies in the cloud + IBranch branch = cloudRepository.getBranch(); + INode cloudModelNode = new PNodeAdapter(modelNodeId, branch); + Iterable dependenciesInCloud = cloudModelNode.getChildren(LINKS.usedLanguages$QK4E.getName()); + + // For each import in the cloud add it if not present in MPS or otherwise ensure all properties are the same + for (final INode dependencyInCloud : Sequence.fromIterable(dependenciesInCloud)) { + INode matchingDependencyInMPS = ListSequence.fromList(dependenciesInMPS).findFirst(new IWhereFilter() { + public boolean accept(INode dependencyInMPS) { + return Objects.equals(dependencyInCloud.getPropertyValue(PROPS.uuid$lpJp.getName()), dependencyInMPS.getPropertyValue(PROPS.uuid$lpJp.getName())); + } + }); + if (matchingDependencyInMPS == null) { + if (Objects.equals(dependencyInCloud.getConcept().getLongName(), (CONCEPTS.DevkitDependency$Ns.getLanguage().getQualifiedName() + "." + CONCEPTS.DevkitDependency$Ns.getName()))) { + SRepository repo = model.getRepository(); + String devKitUUID = dependencyInCloud.getPropertyValue(PROPS.uuid$lpJp.getName()); + DevKit devKit = ((DevKit) repo.getModule(ModuleId.regular(UUID.fromString(devKitUUID)))); + SModuleReference devKitModuleReference = devKit.getModuleReference(); + SModelUtils.addDevKit(mpsModelNode.getElement(), devKitModuleReference); + } else if (Objects.equals(dependencyInCloud.getConcept().getLongName(), (CONCEPTS.SingleLanguageDependency$_9.getLanguage().getQualifiedName() + "." + CONCEPTS.SingleLanguageDependency$_9.getName()))) { + SRepository repo = model.getRepository(); + String languageUUID = dependencyInCloud.getPropertyValue(PROPS.uuid$lpJp.getName()); + Language language = ((Language) repo.getModule(ModuleId.regular(UUID.fromString(languageUUID)))); + SLanguage sLanguage = MetaAdapterFactory.getLanguage(language.getModuleReference()); + SModelUtils.addLanguageImport(mpsModelNode.getElement(), sLanguage, Integer.parseInt(dependencyInCloud.getPropertyValue(PROPS.version$ApUL.getName()))); + } else { + throw new UnsupportedOperationException("Unknown dependency with concept " + dependencyInCloud.getConcept().getLongName()); + } + } else { + // We use this method to avoid using set, if it is not strictly necessary, which may be not supported + INodeUtils.copyPropertyIfNecessary(matchingDependencyInMPS, dependencyInCloud, PROPS.name$lpYq); + INodeUtils.copyPropertyIfNecessary(matchingDependencyInMPS, dependencyInCloud, PROPS.version$ApUL); + } + } + + // For each import not in Cloud remove it + for (INode dependencyInMPS : ListSequence.fromList(dependenciesInMPS)) { + if (dependencyInMPS instanceof DevKitDependencyAsNode) { + INode matchingDependencyInCloud = null; + for (INode dependencyInCloud : Sequence.fromIterable(dependenciesInCloud)) { + if (Objects.equals(dependencyInMPS.getPropertyValue(PROPS.uuid$lpJp.getName()), dependencyInCloud.getPropertyValue(PROPS.uuid$lpJp.getName()))) { + matchingDependencyInCloud = dependencyInCloud; + } + } + if (matchingDependencyInCloud == null) { + DefaultSModelDescriptor dsmd = ((DefaultSModelDescriptor) mpsModelNode.getElement()); + DevKitDependencyAsNode depToRemove = (DevKitDependencyAsNode) dependencyInMPS; + SModuleReference moduleReference = ((SModuleReference) ReflectionUtil.readField(SingleLanguageDependencyAsNode.class, depToRemove, "moduleReference")); + SLanguage languageToRemove = MetaAdapterFactory.getLanguage(moduleReference); + dsmd.deleteLanguageId(languageToRemove); + } + } else if (dependencyInMPS instanceof SingleLanguageDependencyAsNode) { + INode matchingDependencyInCloud = null; + for (INode dependencyInCloud : Sequence.fromIterable(dependenciesInCloud)) { + if (Objects.equals(dependencyInMPS.getPropertyValue(PROPS.uuid$lpJp.getName()), dependencyInCloud.getPropertyValue(PROPS.uuid$lpJp.getName()))) { + matchingDependencyInCloud = dependencyInCloud; + } + } + if (matchingDependencyInCloud == null) { + DefaultSModelDescriptor dsmd = ((DefaultSModelDescriptor) mpsModelNode.getElement()); + SingleLanguageDependencyAsNode depToRemove = (SingleLanguageDependencyAsNode) dependencyInMPS; + SModuleReference moduleReference = depToRemove.getModuleReference(); + SLanguage languageToRemove = MetaAdapterFactory.getLanguage(moduleReference); + dsmd.deleteLanguageId(languageToRemove); + } + } else { + throw new RuntimeException("Unknown dependency type: " + dependencyInMPS.getClass().getName()); + } + + } + } + }); + return Unit.INSTANCE; + } + }); + } + + public void syncModelImportsFromMPS() { + new PArea(getBranch()).executeWrite(new Function0() { + public Unit invoke() { + // First get the dependencies in MPS. Model imports do not include implicit ones + SModelAsNode mpsModelNode = SModelAsNode.wrap(model); + List dependenciesInMPS = IterableOfINodeUtils.toCastedList(mpsModelNode.getChildren(LINKS.modelImports$8DOI.getName())); + + // Then get the dependencies in the cloud + IBranch branch = getBranch(); + INode cloudModelNode = new PNodeAdapter(modelNodeId, branch); + Iterable dependenciesInCloud = cloudModelNode.getChildren(LINKS.modelImports$8DOI.getName()); + + // For each import in MPS, add it if not present in the cloud, or otherwise ensure all properties are the same + for (ModelImportAsNode dependencyInMPS : ListSequence.fromList(dependenciesInMPS)) { + INode modelImportedInMps = dependencyInMPS.getReferenceTarget(LINKS.model$GJHn.getName()); + if (modelImportedInMps != null) { + final String modelIDimportedInMPS = modelImportedInMps.getPropertyValue(PROPS.id$lDUo.getName()); + INode matchingDependencyInCloud = Sequence.fromIterable(dependenciesInCloud).findFirst(new IWhereFilter() { + public boolean accept(INode dependencyInCloud) { + INode modelImportedInCloud = dependencyInCloud.getReferenceTarget(LINKS.model$GJHn.getName()); + if (modelImportedInCloud == null) { + return false; + } + String modelIDimportedInCloud = modelImportedInCloud.getPropertyValue(PROPS.id$lDUo.getName()); + return Objects.equals(modelIDimportedInMPS, modelIDimportedInCloud); + } + }); + if (matchingDependencyInCloud == null) { + INodeUtils.replicateChild(cloudModelNode, LINKS.modelImports$8DOI.getName(), dependencyInMPS); + } else { + // no properties to set here + } + } + } + + // For each import not in MPS, remove it + for (INode dependencyInCloud : Sequence.fromIterable(dependenciesInCloud)) { + INode modelImportedInCloud = dependencyInCloud.getReferenceTarget(LINKS.model$GJHn.getName()); + if (modelImportedInCloud != null) { + final String modelIDimportedInCloud = modelImportedInCloud.getPropertyValue(PROPS.id$lDUo.getName()); + INode matchingDependencyInMPS = Sequence.fromIterable(dependenciesInCloud).findFirst(new IWhereFilter() { + public boolean accept(INode dependencyInMPS) { + INode modelImportedInMPS = dependencyInMPS.getReferenceTarget(LINKS.model$GJHn.getName()); + if (modelImportedInMPS == null) { + return false; + } + String modelIDimportedInMPS = modelImportedInMPS.getPropertyValue(PROPS.id$lDUo.getName()); + return Objects.equals(modelIDimportedInCloud, modelIDimportedInMPS); + } + }); + if (matchingDependencyInMPS == null) { + cloudModelNode.removeChild(dependencyInCloud); + } + } + } + return Unit.INSTANCE; + } + }); + } + + private static boolean isNullModel(INode model) { + if (model == null) { + return true; + } + if (model instanceof SModelAsNode) { + SModelAsNode sModelAsNode = ((SModelAsNode) model); + if (sModelAsNode.getElement() == null) { + return true; + } + } + return false; + } + + public static void syncModelImportsToMPS(final ITree tree, final SModel model, final long modelNodeId, final ICloudRepository cloudRepository) { + new PArea(cloudRepository.getBranch()).executeRead(new Function0() { + public Unit invoke() { + ModelAccess.runInWriteActionIfNeeded(model, new Runnable() { + @Override + public void run() { + // First get the dependencies in MPS + SModelAsNode mpsModelNode = SModelAsNode.wrap(model); + List dependenciesInMPS = IterableOfINodeUtils.toCastedList(mpsModelNode.getChildren(LINKS.modelImports$8DOI.getName())); + + // Then get the dependencies in the cloud + IBranch branch = cloudRepository.getBranch(); + INode cloudModelNode = new PNodeAdapter(modelNodeId, branch); + Iterable dependenciesInCloud = cloudModelNode.getChildren(LINKS.modelImports$8DOI.getName()); + + // For each import in Cloud add it if not present in MPS or otherwise ensure all properties are the same + for (INode dependencyInCloud : Sequence.fromIterable(dependenciesInCloud)) { + INode modelImportedInCloud = dependencyInCloud.getReferenceTarget(LINKS.model$GJHn.getName()); + if (!(isNullModel(modelImportedInCloud))) { + final String modelIDimportedInCloud = modelImportedInCloud.getPropertyValue(PROPS.id$lDUo.getName()); + INode matchingDependencyInMps = ListSequence.fromList(dependenciesInMPS).findFirst(new IWhereFilter() { + public boolean accept(ModelImportAsNode dependencyInMPS) { + INode modelImportedInMPS = dependencyInMPS.getReferenceTarget(LINKS.model$GJHn.getName()); + if (modelImportedInMPS == null) { + return false; + } + String modelIDimportedInMPS = modelImportedInMPS.getPropertyValue(PROPS.id$lDUo.getName()); + return Objects.equals(modelIDimportedInCloud, modelIDimportedInMPS); + } + }); + if (matchingDependencyInMps == null) { + // Model imports have to be added to the underlying SModel using MPS APIs, not the generic reflective INode APIs + + // First we build the Module Reference + INode moduleContainingModelImportedInCloud = modelImportedInCloud.getParent(); + String nameOfModuleContainingModelImportedInCloud = moduleContainingModelImportedInCloud.getPropertyValue(PROPS.name$MnvL.getName()); + String idOfModuleContainingModelImportedInCloud = moduleContainingModelImportedInCloud.getPropertyValue(PROPS.id$7MjP.getName()); + SModuleReference moduleRef = new ModuleReference(nameOfModuleContainingModelImportedInCloud, ModuleId.fromString(idOfModuleContainingModelImportedInCloud)); + + // Then we build the ModelReference + SModelId modelID = jetbrains.mps.smodel.SModelId.fromString(modelIDimportedInCloud); + String modelName = modelImportedInCloud.getPropertyValue(PROPS.name$MnvL.getName()); + SModelReference refToModelToImport = new SModelReference(moduleRef, modelID, modelName); + + // We can now add the import + ModelImports modelImports = new ModelImports(model); + modelImports.addModelImport(refToModelToImport); + } else { + // no properties to set here + } + } + } + + // For each import not in Cloud remove it + for (ModelImportAsNode dependencyInMPS : ListSequence.fromList(dependenciesInMPS)) { + INode modelImportedInMPS = dependencyInMPS.getReferenceTarget(LINKS.model$GJHn.getName()); + if (modelImportedInMPS != null) { + final String modelIDimportedInMPS = modelImportedInMPS.getPropertyValue(PROPS.id$lDUo.getName()); + INode matchingDependencyInCloud = Sequence.fromIterable(dependenciesInCloud).findFirst(new IWhereFilter() { + public boolean accept(INode dependencyInCloud) { + INode modelImportedInCloud = dependencyInCloud.getReferenceTarget(LINKS.model$GJHn.getName()); + if (isNullModel(modelImportedInCloud)) { + return false; + } + String modelIDimportedInCloud = modelImportedInCloud.getPropertyValue(PROPS.id$lDUo.getName()); + return Objects.equals(modelIDimportedInMPS, modelIDimportedInCloud); + } + }); + if (matchingDependencyInCloud == null) { + SModelDescriptorStub dsmd = ((SModelDescriptorStub) mpsModelNode.getElement()); + ModelImportAsNode depToRemove = dependencyInMPS; + org.jetbrains.mps.openapi.model.SModelReference modelReferenceToRemove = depToRemove.getElement().getReference(); + dsmd.deleteModelImport(modelReferenceToRemove); + } + } + } + } + }); + return Unit.INSTANCE; + } + }); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink usedLanguages$QK4E = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x4aaf28cf2092e98eL, "usedLanguages"); + /*package*/ static final SContainmentLink modelImports$8DOI = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x58dbe6e4d4f32eb8L, "modelImports"); + /*package*/ static final SReferenceLink model$GJHn = MetaAdapterFactory.getReferenceLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x58dbe6e4d4f332a3L, 0x58dbe6e4d4f332a4L, "model"); + } + + private static final class PROPS { + /*package*/ static final SProperty uuid$lpJp = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x7c527144386aca0fL, 0x7c527144386aca12L, "uuid"); + /*package*/ static final SProperty name$lpYq = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x7c527144386aca0fL, 0x7c527144386aca13L, "name"); + /*package*/ static final SProperty version$ApUL = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529917dL, 0x1e9fde9535299183L, "version"); + /*package*/ static final SProperty id$lDUo = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x244b85440ee67212L, "id"); + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$7MjP = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x3aa34013f2a802e0L, "id"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept DevkitDependency$Ns = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x7c527144386aca16L, "org.modelix.model.repositoryconcepts.structure.DevkitDependency"); + /*package*/ static final SConcept SingleLanguageDependency$_9 = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x1e9fde953529917dL, "org.modelix.model.repositoryconcepts.structure.SingleLanguageDependency"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerConnection.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerConnection.java new file mode 100644 index 00000000..e4453f1e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerConnection.java @@ -0,0 +1,614 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.client.RestWebModelClient; +import java.util.Map; +import org.modelix.model.client.ActiveBranch; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.modelix.model.api.IBranchListener; +import com.intellij.util.messages.MessageBusConnection; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.project.ProjectManagerListener; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import java.util.Objects; +import jetbrains.mps.ide.project.ProjectHelper; +import kotlin.jvm.functions.Function0; +import org.modelix.common.InstanceJwtToken; +import org.modelix.model.mpsplugin.plugin.ModelixConfigurationSystemProperties; +import org.modelix.model.mpsplugin.plugin.EModelixExecutionMode; +import java.util.Arrays; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import kotlin.jvm.functions.Function2; +import kotlin.Unit; +import org.modelix.model.client.ConnectionListener; +import javax.swing.SwingUtilities; +import java.util.function.Supplier; +import org.apache.log4j.Level; +import org.modelix.common.AuthorOverride; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.area.PArea; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; +import jetbrains.mps.internal.collections.runtime.IListSequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; +import org.modelix.model.mpsadapters.mps.SNodeAPI; +import org.modelix.model.api.IBranch; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.ITransaction; +import org.modelix.model.api.ITree; +import org.modelix.model.mpsadapters.mps.NodeToSNodeAdapter; +import org.modelix.model.api.PNodeAdapter; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import org.modelix.model.api.IWriteTransaction; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.modelix.model.client.ReplicatedRepository; +import org.modelix.model.client.IModelClient; +import java.util.function.Consumer; +import de.q60.mps.incremental.runtime.DependencyBroadcaster; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SConcept; + +public class ModelServerConnection { + private static final Logger LOG = LogManager.getLogger(ModelServerConnection.class); + private static final RepositoryId INFO_REPOSITORY_ID = new RepositoryId("info"); + public static final RepositoryId UI_STATE_REPOSITORY_ID = new RepositoryId("uistate"); + private String SETTINGS_KEY_PREFIX = ModelServerConnection.class.getName() + ".token/"; + + public static final String DEFAULT_REPOSITORY_ID = "default"; + + private String baseUrl; + private RestWebModelClient client; + private MpsReplicatedRepository infoTree; + private final Map activeBranches = MapSequence.fromMap(new HashMap()); + private List listeners = ListSequence.fromList(new ArrayList()); + private String id; + private String email; + private Map invalidationListeners = MapSequence.fromMap(new HashMap()); + private MessageBusConnection messageBusConnection; + private Map bindings = MapSequence.fromMap(new HashMap()); + + public ModelServerConnection(String baseUrl) { + if (LOG.isDebugEnabled()) { + LOG.debug("ModelServerConnection.init(" + baseUrl + ")"); + } + messageBusConnection = ApplicationManager.getApplication().getMessageBus().connect(); + messageBusConnection.subscribe(ProjectManager.TOPIC, new ProjectManagerListener() { + @Override + public void projectClosing(@NotNull final Project closingProject) { + for (ProjectBinding closingProjectBinding : Sequence.fromIterable(MapSequence.fromMap(bindings).values()).translate(new ITranslator2() { + public Iterable translate(RootBinding it) { + return it.getAllBindings(); + } + }).ofType(ProjectBinding.class).where(new IWhereFilter() { + public boolean accept(ProjectBinding it) { + return Objects.equals(ProjectHelper.toIdeaProject(it.getProject()), closingProject); + } + }).toListSequence()) { + removeBinding(closingProjectBinding); + } + } + }); + this.baseUrl = baseUrl; + Function0 workspaceTokenProvider = new Function0() { + public String invoke() { + return InstanceJwtToken.token; + } + }; + Function0 tokenProvider = (ModelixConfigurationSystemProperties.getExecutionMode() == EModelixExecutionMode.PROJECTOR ? workspaceTokenProvider : null); + client = new RestWebModelClient(baseUrl, tokenProvider, Arrays.asList(new ConnectionListenerForForbiddenMessage(baseUrl))); + final Wrappers._boolean connectedFirstTime = new Wrappers._boolean(true); + client.addStatusListener(new Function2() { + public Unit invoke(RestWebModelClient.ConnectionStatus oldStatus, RestWebModelClient.ConnectionStatus newStatus) { + if (newStatus == RestWebModelClient.ConnectionStatus.CONNECTED && connectedFirstTime.value) { + connectedFirstTime.value = false; + onConnect(); + } + for (IListener l : ListSequence.fromList(listeners)) { + l.connectionStatusChanged(newStatus == RestWebModelClient.ConnectionStatus.CONNECTED); + } + return Unit.INSTANCE; + } + }); + } + + /** + * It seems that several connections are open at the same time: we do not want to show + * error messages multiple times, so we use a shared state of the connection + */ + private static class ConnectionListenerForForbiddenMessage implements ConnectionListener { + private static Map inForbiddenStateByURL = MapSequence.fromMap(new HashMap()); + private String baseUrl; + private ConnectionListenerForForbiddenMessage(String baseUrl) { + this.baseUrl = baseUrl; + } + @Override + public void receivedForbiddenResponse() { + if (!(inForbiddenState())) { + MapSequence.fromMap(inForbiddenStateByURL).put(baseUrl, true); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ModelixNotifications.notifyError("Forbidden Access", "Unauthorized to connect to Model Server " + baseUrl + ". Check you are logged in and have the right to access that Model Server"); + } + }); + } + } + @Override + public void receivedSuccessfulResponse() { + MapSequence.fromMap(inForbiddenStateByURL).put(baseUrl, false); + } + + private boolean inForbiddenState() { + if (MapSequence.fromMap(inForbiddenStateByURL).containsKey(baseUrl)) { + return MapSequence.fromMap(inForbiddenStateByURL).get(baseUrl); + } else { + return false; + } + } + } + + public RootBinding getRootBinding(RepositoryId repositoryId) { + RootBinding rootBinding = MapSequence.fromMap(bindings).get(repositoryId); + if (rootBinding == null) { + rootBinding = new RootBinding(this, repositoryId); + MapSequence.fromMap(bindings).put(repositoryId, rootBinding); + } + return rootBinding; + } + + @Deprecated + public void reconnect() { + client.reconnect(); + } + + private void onConnect() { + id = client.get("server-id"); + if ((id == null || id.length() == 0)) { + // TODO 'repositoryId' was renamed to 'server-id'. After migrating all servers this request is not required anymore. + id = client.get("repositoryId"); + } + if ((id == null || id.length() == 0)) { + throw new RuntimeException(baseUrl + " doesn't provide an ID"); + } + if (infoTree == null) { + infoTree = new MpsReplicatedRepository(client, INFO_REPOSITORY_ID, ActiveBranch.DEFAULT_BRANCH_NAME, new Supplier() { + public String get() { + return getAuthor(); + } + }); + } + try { + email = client.getEmail(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to read the users e-mail address", ex); + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("connected to " + baseUrl); + } + } + + public String getEmail() { + return email; + } + + public String getAuthor() { + String email = getEmail(); + if (Objects.equals(email, "")) { + email = null; + } + return AuthorOverride.apply(email); + } + + public boolean isConnected() { + RestWebModelClient.ConnectionStatus status = check_v06aqd_a0a0fb(client); + return status != RestWebModelClient.ConnectionStatus.NEW && status != RestWebModelClient.ConnectionStatus.WAITING_FOR_TOKEN; + } + + public String getId() { + return this.id; + } + + protected void checkConnected() { + RestWebModelClient.ConnectionStatus connectionStatus = check_v06aqd_a0a0jb(client); + if (connectionStatus != RestWebModelClient.ConnectionStatus.CONNECTED) { + client.reconnect(); + } + if (!(isConnected())) { + throw new IllegalStateException("Not connected. Client is in status " + connectionStatus); + } + } + + public List getAllRepositories() { + return new PArea(getInfoBranch()).executeWrite(new Function0>() { + public List invoke() { + return SLinkOperations.getChildren(getInfo(), LINKS.repositories$b56J); + } + }); + } + + public int getAllRepositoriesCount() { + return new PArea(getInfoBranch()).executeWrite(new Function0() { + public Integer invoke() { + return ListSequence.fromList(SLinkOperations.getChildren(getInfo(), LINKS.repositories$b56J)).count(); + } + }); + } + + public SNode getRepositoryInfoById(final String repositoryId) { + SNode repositoryInfo = new PArea(getInfoBranch()).executeRead(new Function0() { + public SNode invoke() { + SNode modelServerInfo = getInfo(); + return ListSequence.fromList(SLinkOperations.getChildren(modelServerInfo, LINKS.repositories$b56J)).findFirst(new IWhereFilter() { + public boolean accept(SNode it) { + return Objects.equals(SPropertyOperations.getString(it, PROPS.id$baYB), repositoryId); + } + }); + } + }); + if (repositoryInfo == null) { + List knownRepositoryIds = new PArea(getInfoBranch()).executeRead(new Function0>() { + public IListSequence invoke() { + SNode modelServerInfo = getInfo(); + return ListSequence.fromList(SLinkOperations.getChildren(modelServerInfo, LINKS.repositories$b56J)).select(new ISelector() { + public String select(SNode it) { + return SPropertyOperations.getString(it, PROPS.id$baYB); + } + }).toListSequence(); + } + }); + + throw new IllegalArgumentException("RepositoryInfo with ID " + repositoryId + " not found. Known repository ids: " + knownRepositoryIds); + } + return repositoryInfo; + } + + public SNode addRepository(final String id) { + return new PArea(getInfoBranch()).executeWrite(new Function0() { + public SNode invoke() { + SNode modelServerInfo = getInfo(); + SNode repositoryInfo = SNodeOperations.cast(SNodeAPI.addNewChild(modelServerInfo, LINKS.repositories$b56J), CONCEPTS.RepositoryInfo$5Y); + SPropertyOperations.assign(repositoryInfo, PROPS.id$baYB, id); + SNode branchInfo = SNodeOperations.cast(SNodeAPI.addNewChild(repositoryInfo, LINKS.branches$b5_g), CONCEPTS.BranchInfo$6t); + SPropertyOperations.assign(branchInfo, PROPS.name$MnvL, ActiveBranch.DEFAULT_BRANCH_NAME); + return repositoryInfo; + } + }); + } + + public void removeRepository(final String id) { + new PArea(getInfoBranch()).executeWrite(new Function0() { + public SNode invoke() { + SNode info = getInfo(); + return SNodeOperations.deleteNode(ListSequence.fromList(SLinkOperations.getChildren(info, LINKS.repositories$b56J)).findFirst(new IWhereFilter() { + public boolean accept(SNode it) { + return Objects.equals(SPropertyOperations.getString(it, PROPS.id$baYB), id); + } + })); + } + }); + } + + public boolean hasProjectBinding(final RepositoryId repositoryId, final long projectNodeId) { + return Sequence.fromIterable(getProjectBindings()).any(new IWhereFilter() { + public boolean accept(ProjectBinding it) { + return Objects.equals(it.getCloudRepository().getRepositoryId(), repositoryId) && Objects.equals(it.getProjectNodeId(), projectNodeId); + } + }); + } + + public Iterable getProjectBindings() { + return Sequence.fromIterable(MapSequence.fromMap(bindings).values()).translate(new ITranslator2() { + public Iterable translate(RootBinding it) { + return it.getAllBindings(); + } + }).ofType(ProjectBinding.class); + } + + public void addBinding(RepositoryId repositoryId, final Binding binding, Runnable callback) { + binding.setOwner(getRootBinding(repositoryId)); + binding.activate(callback); + } + + public void addBinding(RepositoryId repositoryId, final Binding binding) { + addBinding(repositoryId, binding, null); + } + + public void removeBinding(Binding binding) { + binding.deactivate(null); + binding.setOwner(null); + } + + public boolean hasModuleBinding(final RepositoryId repositoryId, final long moduleNodeId) { + return Sequence.fromIterable(getModuleBindings()).any(new IWhereFilter() { + public boolean accept(ModuleBinding it) { + return Objects.equals(it.getCloudRepository().getRepositoryId(), repositoryId) && Objects.equals(it.getModuleNodeId(), moduleNodeId); + } + }); + } + public List getModuleBinding(final RepositoryId repositoryId, final long moduleNodeId) { + return Sequence.fromIterable(getModuleBindings()).where(new IWhereFilter() { + public boolean accept(ModuleBinding it) { + return Objects.equals(it.getCloudRepository().getRepositoryId(), repositoryId) && Objects.equals(it.getModuleNodeId(), moduleNodeId); + } + }).toListSequence(); + } + + public Iterable getModuleBindings() { + return Sequence.fromIterable(MapSequence.fromMap(bindings).values()).translate(new ITranslator2() { + public Iterable translate(RootBinding it) { + return it.getAllBindings(); + } + }).ofType(ModuleBinding.class); + } + + public IBranch getInfoBranch() { + checkConnected(); + return check_v06aqd_a1a26(infoTree); + } + public T computeRead(final RepositoryId repositoryId, final Function0 producer) { + return this.getInfoBranch().computeRead(new Function0() { + public T invoke() { + ActiveBranch activeBranch = ModelServerConnection.this.getActiveBranch(repositoryId); + final IBranch branch = activeBranch.getBranch(); + return new PArea(branch).executeRead(new Function0() { + public T invoke() { + return producer.invoke(); + } + }); + } + }); + } + + @Nullable + public SNode getInfo() { + if (infoTree == null) { + return null; + } + checkConnected(); + SNode result = new PArea(infoTree.getBranch()).executeRead(new Function0() { + public SNode invoke() { + ITransaction t = infoTree.getBranch().getTransaction(); + Iterable allChildren_ = t.getAllChildren(ITree.ROOT_ID); + Iterable allChildren = Sequence.fromIterable(allChildren_).select(new ISelector() { + public SNode select(Long it) { + return (SNode) NodeToSNodeAdapter.wrap(new PNodeAdapter(it, infoTree.getBranch())); + } + }); + return Sequence.fromIterable(SNodeOperations.ofConcept(allChildren, CONCEPTS.ModelServerInfo$5v)).first(); + } + }); + if (result == null) { + SharedExecutors.FIXED.submit(new _Adapters._return_P0_E0_to_Runnable_adapter(new _FunctionTypes._return_P0_E0() { + public SNode invoke() { + return new PArea(infoTree.getBranch()).executeWrite(new Function0() { + public SNode invoke() { + IWriteTransaction t = infoTree.getBranch().getWriteTransaction(); + long id = t.addNewChild(ITree.ROOT_ID, "info", -1, SConceptAdapter.wrap(CONCEPTS.ModelServerInfo$5v)); + SNode repoInfo = SNodeOperations.cast(NodeToSNodeAdapter.wrap(new PNodeAdapter(id, infoTree.getBranch())), CONCEPTS.ModelServerInfo$5v); + + addRepository(DEFAULT_REPOSITORY_ID); + + return repoInfo; + } + }); + } + })); + } + return result; + } + + public ActiveBranch getActiveBranch(RepositoryId repositoryId) { + checkConnected(); + synchronized (activeBranches) { + ActiveBranch ab = MapSequence.fromMap(activeBranches).get(repositoryId); + if (ab == null) { + ab = new ActiveBranch(client, repositoryId, null, new Function0() { + public String invoke() { + return getAuthor(); + } + }) { + @NotNull + @Override + protected ReplicatedRepository createReplicatedRepository(@NotNull IModelClient client, @NotNull RepositoryId repositoryId, @NotNull String branchName, @NotNull final Function0 user) { + return new MpsReplicatedRepository(client, repositoryId, branchName, new Supplier() { + public String get() { + return user.invoke(); + } + }); + } + }; + InvalidationBranchListener invalidationListener = new InvalidationBranchListener(ab); + MapSequence.fromMap(invalidationListeners).put(ab, invalidationListener); + ab.addListener(invalidationListener); + MapSequence.fromMap(activeBranches).put(repositoryId, ab); + } + return ab; + } + } + + public Iterable getActiveBranches() { + synchronized (activeBranches) { + return Sequence.fromIterable(MapSequence.fromMap(activeBranches).values()).toListSequence(); + } + } + + public synchronized void dispose() { + try { + messageBusConnection.disconnect(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + try { + check_v06aqd_a0a1a17(client); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + try { + check_v06aqd_a0a2a17(infoTree); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + + for (RootBinding binding : Sequence.fromIterable(MapSequence.fromMap(bindings).values())) { + binding.deactivate(null); + } + synchronized (activeBranches) { + for (ActiveBranch ab : Sequence.fromIterable(MapSequence.fromMap(activeBranches).values())) { + try { + IBranchListener invalidationListener = MapSequence.fromMap(invalidationListeners).removeKey(ab); + if (invalidationListener != null) { + ab.removeListener(invalidationListener); + } + ab.dispose(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + MapSequence.fromMap(activeBranches).clear(); + } + } + + public String getBaseUrl() { + return baseUrl; + } + + public IModelClient getClient() { + checkConnected(); + return this.client; + } + + @Override + public String toString() { + return baseUrl; + } + + public void addListener(IListener l) { + List newListeners = ListSequence.fromListWithValues(new ArrayList(), listeners); + ListSequence.fromList(newListeners).addElement(l); + listeners = newListeners; + } + + public void removeListener(IListener l) { + List newListeners = ListSequence.fromListWithValues(new ArrayList(), listeners); + ListSequence.fromList(newListeners).removeElement(l); + listeners = newListeners; + } + + public void whenConnected(final Consumer consumer) { + if (this.isConnected()) { + consumer.accept(this); + } else { + final IListener listener = new IListener() { + @Override + public void connectionStatusChanged(boolean connected) { + if (connected) { + consumer.accept(ModelServerConnection.this); + ModelServerConnection.this.removeListener(this); + } + } + }; + this.addListener(listener); + } + } + + public interface IListener { + default void connectionStatusChanged(boolean connected) { + } + default void bindingAdded(Binding binding) { + } + default void bindingRemoved(Binding binding) { + } + default void bindingActivated(Binding binding) { + } + default void bindingDeactivated(Binding binding) { + } + } + + public class InvalidationBranchListener implements IBranchListener { + private ActiveBranch branch; + public InvalidationBranchListener(ActiveBranch branch) { + this.branch = branch; + } + @Override + public void treeChanged(@Nullable ITree oldTree, @NotNull ITree newTree) { + if (oldTree == null) { + return; + } + TreeChangesCollector changesCollector = new TreeChangesCollector(branch.getBranch()); + newTree.visitChanges(oldTree, changesCollector); + DependencyBroadcaster.INSTANCE.dependenciesChanged(changesCollector.getChanges()); + } + } + private static RestWebModelClient.ConnectionStatus check_v06aqd_a0a0fb(RestWebModelClient checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getConnectionStatus(); + } + return null; + } + private static RestWebModelClient.ConnectionStatus check_v06aqd_a0a0jb(RestWebModelClient checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getConnectionStatus(); + } + return null; + } + private static IBranch check_v06aqd_a1a26(MpsReplicatedRepository checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getBranch(); + } + return null; + } + private static void check_v06aqd_a0a1a17(RestWebModelClient checkedDotOperand) { + if (null != checkedDotOperand) { + checkedDotOperand.dispose(); + } + + } + private static void check_v06aqd_a0a2a17(MpsReplicatedRepository checkedDotOperand) { + if (null != checkedDotOperand) { + checkedDotOperand.dispose(); + } + + } + + private static final class LINKS { + /*package*/ static final SContainmentLink repositories$b56J = MetaAdapterFactory.getContainmentLink(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcbfL, 0x62b7d9b07cecbcc2L, "repositories"); + /*package*/ static final SContainmentLink branches$b5_g = MetaAdapterFactory.getContainmentLink(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, 0x62b7d9b07cecbcc4L, "branches"); + } + + private static final class PROPS { + /*package*/ static final SProperty id$baYB = MetaAdapterFactory.getProperty(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, 0x62b7d9b07cecbcc6L, "id"); + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept RepositoryInfo$5Y = MetaAdapterFactory.getConcept(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, "org.modelix.model.runtimelang.structure.RepositoryInfo"); + /*package*/ static final SConcept BranchInfo$6t = MetaAdapterFactory.getConcept(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc1L, "org.modelix.model.runtimelang.structure.BranchInfo"); + /*package*/ static final SConcept ModelServerInfo$5v = MetaAdapterFactory.getConcept(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcbfL, "org.modelix.model.runtimelang.structure.ModelServerInfo"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerConnections.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerConnections.java new file mode 100644 index 00000000..28a9dc6f --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerConnections.java @@ -0,0 +1,225 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.model.api.IBranch; +import org.modelix.model.api.PBranch; +import de.q60.mps.shadowmodels.runtime.model.persistent.SM_PTree; +import org.modelix.model.client.IdGenerator; +import org.modelix.model.api.IBranchListener; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.ITree; +import org.jetbrains.annotations.NotNull; +import de.q60.mps.incremental.runtime.DependencyBroadcaster; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import java.util.Set; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import org.modelix.model.area.IArea; +import org.jetbrains.mps.openapi.module.SRepository; +import org.modelix.model.area.PArea; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import org.modelix.model.client.ActiveBranch; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import org.modelix.model.area.CompositeArea; +import org.modelix.model.mpsadapters.mps.MPSArea; +import java.util.Objects; +import org.apache.log4j.Level; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.lazy.RepositoryId; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; +import org.modelix.model.mpsadapters.mps.NodeToSNodeAdapter; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.api.IConcept; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class ModelServerConnections { + private static final Logger LOG = LogManager.getLogger(ModelServerConnections.class); + private static ModelServerConnections ourInstance = new ModelServerConnections(); + public static final IBranch LOCAL_UI_STATE_BRANCH = new PBranch(SM_PTree.EMPTY, IdGenerator.Companion.getInstance(1)); + + static { + LOCAL_UI_STATE_BRANCH.addListener(new IBranchListener() { + @Override + public void treeChanged(@Nullable ITree oldTree, @NotNull ITree newTree) { + if (oldTree == null) { + return; + } + TreeChangesCollector changesCollector = new TreeChangesCollector(LOCAL_UI_STATE_BRANCH); + newTree.visitChanges(oldTree, changesCollector); + DependencyBroadcaster.INSTANCE.dependenciesChanged(changesCollector.getChanges()); + } + }); + } + + public static ModelServerConnections getInstance() { + return ourInstance; + } + + private List modelServers = ListSequence.fromList(new ArrayList()); + private Set listeners = SetSequence.fromSet(new HashSet()); + + public ModelServerConnections() { + // we used to initialize repositories here, reading the configuration + // we do not do that here anymore + } + + public IArea getArea() { + return getArea(CommandHelper.getSRepository()); + } + + public IArea getArea(SRepository mpsRepository) { + Iterable cloudAreas = Sequence.fromIterable(getModelServers()).where(new IWhereFilter() { + public boolean accept(ModelServerConnection it) { + return it.isConnected(); + } + }).translate(new ITranslator2() { + public Iterable translate(ModelServerConnection it) { + it.getActiveBranch(ModelServerConnection.UI_STATE_REPOSITORY_ID); + return it.getActiveBranches(); + } + }).select(new ISelector() { + public PArea select(ActiveBranch it) { + IBranch branch = it.getBranch(); + return new PArea(branch); + } + }).where(new NotNullWhereFilter()); + CompositeArea area = new CompositeArea(Sequence.fromIterable(Sequence.singleton(new MPSArea(mpsRepository))).concat(Sequence.fromIterable(cloudAreas)).concat(Sequence.fromIterable(Sequence.singleton(new PArea(LOCAL_UI_STATE_BRANCH)))).toListSequence()); + return area; + } + + public void addListener(IListener l) { + SetSequence.fromSet(listeners).addElement(l); + } + + public void removeListener(IListener l) { + SetSequence.fromSet(listeners).removeElement(l); + } + + public boolean existModelServer(String url) { + return getModelServer(url) != null; + } + public ModelServerConnection getModelServer(final String url) { + if (!(url.endsWith("/"))) { + return getModelServer(url + "/"); + } + return ListSequence.fromList(this.modelServers).findFirst(new IWhereFilter() { + public boolean accept(ModelServerConnection it) { + return Objects.equals(url, it.getBaseUrl()); + } + }); + } + + public ModelServerConnection addModelServer(String url) { + if (url == null) { + throw new IllegalArgumentException("url should not be null"); + } + if (!(url.endsWith("/"))) { + return addModelServer(url + "/"); + } + if (existModelServer(url)) { + throw new IllegalStateException("The repository with url " + url + " is already present"); + } + ModelServerConnection result = doAddModelServer(url); + // we do not automatically change the persisted configuration, to avoid cycles + return result; + } + + protected ModelServerConnection doAddModelServer(String url) { + ModelServerConnection newRepo = ListSequence.fromList(modelServers).addElement(new ModelServerConnection(url)); + try { + for (IListener l : SetSequence.fromSet(listeners)) { + l.repositoriesChanged(); + } + } catch (Exception t) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", t); + } + ModelixNotifications.notifyError("Failure while adding model server " + url, t.getMessage()); + } + return newRepo; + } + + public void removeModelServer(ModelServerConnection repo) { + ListSequence.fromList(modelServers).removeElement(repo); + // we do not automatically change the persisted configuration, to avoid cycles + for (IListener l : SetSequence.fromSet(listeners)) { + l.repositoriesChanged(); + } + } + + public Iterable getModelServers() { + return modelServers; + } + + public Iterable getConnectedModelServers() { + return ListSequence.fromList(modelServers).where(new IWhereFilter() { + public boolean accept(ModelServerConnection it) { + return it.isConnected(); + } + }); + } + + public Iterable getConnectedTreesInRepositories() { + return ListSequence.fromList(modelServers).where(new IWhereFilter() { + public boolean accept(ModelServerConnection it) { + return it.isConnected(); + } + }).translate(new ITranslator2() { + public Iterable translate(ModelServerConnection it) { + return ModelServerNavigation.trees(it); + } + }); + } + + public SNode resolveCloudModel(String repositoryId) { + ModelServerConnection repo = Sequence.fromIterable(getModelServers()).where(new IWhereFilter() { + public boolean accept(ModelServerConnection it) { + return it.isConnected(); + } + }).first(); + ActiveBranch activeBranch = repo.getActiveBranch(new RepositoryId(repositoryId)); + + return SNodeOperations.cast(NodeToSNodeAdapter.wrap(new PNodeAdapter(ITree.ROOT_ID, activeBranch.getBranch()) { + @Override + public IConcept getConcept() { + return SConceptAdapter.wrap(CONCEPTS.Repository$db); + } + }, MPSModuleRepository.getInstance()), CONCEPTS.Repository$db); + } + + public void dispose() { + for (ModelServerConnection modelServer : ListSequence.fromList(modelServers)) { + modelServer.dispose(); + } + ListSequence.fromList(modelServers).clear(); + } + + public interface IListener { + void repositoriesChanged(); + } + + public ModelServerConnection ensureModelServerIsPresent(String url) { + ModelServerConnection modelServerConnection = this.getModelServer(url); + if (modelServerConnection != null) { + return modelServerConnection; + } else { + return ModelServerConnections.getInstance().addModelServer(url); + } + } + + + private static final class CONCEPTS { + /*package*/ static final SConcept Repository$db = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, "org.modelix.model.repositoryconcepts.structure.Repository"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerNavigation.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerNavigation.java new file mode 100644 index 00000000..c8e16912 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelServerNavigation.java @@ -0,0 +1,45 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import java.util.List; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import jetbrains.mps.internal.collections.runtime.IListSequence; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.modelix.model.lazy.RepositoryId; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; + +public class ModelServerNavigation { + public ModelServerNavigation() { + } + public static List trees(final ModelServerConnection _this) { + final SNode info = _this.getInfo(); + return new PArea(_this.getInfoBranch()).executeRead(new Function0>() { + public IListSequence invoke() { + // We want to obtain a list within the transaction. + // A sequence (which is lazy) would not work + return ListSequence.fromList(SLinkOperations.getChildren(info, LINKS.repositories$b56J)).select(new ISelector() { + public CloudRepository select(SNode it) { + RepositoryId repositoryId = new RepositoryId(SPropertyOperations.getString(it, PROPS.id$baYB)); + return new CloudRepository(_this, repositoryId); + } + }).toListSequence(); + } + }); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink repositories$b56J = MetaAdapterFactory.getContainmentLink(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcbfL, 0x62b7d9b07cecbcc2L, "repositories"); + } + + private static final class PROPS { + /*package*/ static final SProperty id$baYB = MetaAdapterFactory.getProperty(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, 0x62b7d9b07cecbcc6L, "id"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelSynchronizer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelSynchronizer.java new file mode 100644 index 00000000..fc82fa01 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelSynchronizer.java @@ -0,0 +1,708 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.model.api.IBranch; +import org.jetbrains.mps.openapi.model.SModel; +import org.modelix.model.api.ITree; +import org.modelix.model.lazy.IBulkTree; +import org.modelix.model.lazy.PrefetchCache; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.jetbrains.mps.openapi.model.SNode; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import org.apache.log4j.Level; +import org.modelix.model.area.PArea; +import org.modelix.model.api.IWriteTransaction; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.IMapping; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import org.modelix.model.api.ITransaction; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.modelix.model.api.IConcept; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.internal.collections.runtime.CollectionSequence; +import org.jetbrains.mps.openapi.language.SReferenceLink; +import org.modelix.model.api.INode; +import org.modelix.model.api.IProperty; +import org.modelix.model.api.INodeReference; +import org.jetbrains.mps.openapi.module.SRepository; +import org.modelix.model.area.IArea; +import org.modelix.model.area.CompositeArea; +import org.modelix.model.mpsadapters.mps.MPSArea; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.api.NodeUtilKt; +import org.modelix.model.mpsadapters.mps.NodeToSNodeAdapter; +import java.util.Objects; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.util.IterableUtil; +import java.util.List; +import java.util.HashMap; +import java.util.Set; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import org.jetbrains.mps.openapi.language.SConcept; +import org.modelix.model.mpsadapters.mps.SNodeToNodeAdapter; +import jetbrains.mps.internal.collections.runtime.ISelector; +import java.util.Optional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.event.SNodeAddEvent; +import org.jetbrains.mps.openapi.event.SNodeRemoveEvent; +import org.jetbrains.mps.openapi.event.SReferenceChangeEvent; +import jetbrains.mps.project.ModelImporter; +import org.jetbrains.mps.openapi.model.SReference; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class ModelSynchronizer { + private static final Logger LOG = LogManager.getLogger(ModelSynchronizer.class); + public static final String USED_DEVKITS = "usedDevkits"; + public static final String MPS_NODE_ID_PROPERTY_NAME = "#mpsNodeId#"; + + protected NodeMap nodeMap = new NodeMap(new NodeMap.BranchProvider() { + public IBranch getBranch() { + return ModelSynchronizer.this.getBranch(); + } + }); + protected SModel model; + protected long modelNodeId; + private ICloudRepository cloudRepository; + private final PendingReferences pendingReferences = new PendingReferences(); + + public ModelSynchronizer(long modelNodeId, SModel model, ICloudRepository cloudRepository) { + this.model = model; + this.modelNodeId = modelNodeId; + this.cloudRepository = cloudRepository; + } + + public IBranch getBranch() { + return cloudRepository.getBranch(); + } + + public void prefetchModelContent(ITree tree) { + if (tree instanceof IBulkTree) { + ((IBulkTree) tree).getDescendants(modelNodeId, true); + } + } + + public void runAndFlushReferences(Runnable runnable) { + pendingReferences.runAndFlush(runnable); + } + + public void syncModelToMPS(final ITree tree, final boolean withInitialRemoval) { + PrefetchCache.Companion.with(tree, new Function0() { + public Unit invoke() { + if (LOG.isTraceEnabled()) { + LOG.trace("syncModel initialRemoval=" + withInitialRemoval + " on model " + model.getName().getLongName()); + } + if (withInitialRemoval) { + for (SNode root : ListSequence.fromList(ListSequence.fromListWithValues(new ArrayList(), model.getRootNodes())).ofType(SNode.class)) { + ListSequence.fromList(SNodeOperations.getChildren(root)).visitAll(new IVisitor() { + public void visit(SNode it) { + SNodeOperations.deleteNode(it); + } + }); + } + } + pendingReferences.runAndFlush(new Runnable() { + public void run() { + prefetchModelContent(tree); + syncRootNodesToMPS(); + syncModelPropertiesToMPS(tree); + } + }); + return Unit.INSTANCE; + } + }); + } + + public void syncModelPropertiesToMPS(ITree tree) { + ModelPropertiesSynchronizer.syncModelPropertiesToMPS(tree, model, modelNodeId, cloudRepository); + } + + public void fullSyncFromMPS() { + final ITree tree = getBranch().getTransaction().getTree(); + if (!(tree.containsNode(modelNodeId))) { + if (LOG.isEnabledFor(Level.WARN)) { + LOG.warn("Skipping sync for " + this + ", because the model node " + Long.toHexString(modelNodeId) + " doesn't exist in the cloud model"); + } + return; + } + PrefetchCache.Companion.with(tree, new Function0() { + public Unit invoke() { + pendingReferences.runAndFlush(new Runnable() { + public void run() { + prefetchModelContent(tree); + syncModelPropertiesFromMPS(); + syncRootNodesFromMPS(); + } + }); + return Unit.INSTANCE; + } + }); + new PArea(getBranch()).executeWrite(new Function0() { + public Unit invoke() { + return Unit.INSTANCE; + } + }); + } + + protected void syncRootNodesFromMPS() { + IWriteTransaction t = getBranch().getWriteTransaction(); + Map syncedNodes = createChildrenSynchronizer(modelNodeId, LINKS.rootNodes$jxXY.getName()).syncToCloud(t); + for (IMapping syncedNode : MapSequence.fromMap(syncedNodes)) { + syncNodeFromMPS(syncedNode.value(), true); + } + } + + protected void syncRootNodesToMPS() { + ITransaction t = getBranch().getTransaction(); + Map syncedNodes = createChildrenSynchronizer(modelNodeId, LINKS.rootNodes$jxXY.getName()).syncToMPS(t.getTree()); + for (IMapping syncedNode : MapSequence.fromMap(syncedNodes)) { + syncNodeToMPS(syncedNode.key(), t.getTree(), true); + } + } + + public void syncModelPropertiesFromMPS() { + new ModelPropertiesSynchronizer(modelNodeId, model, cloudRepository).syncModelPropertiesFromMPS(); + } + + public void syncUsedLanguagesAndDevKitsFromMPS() { + new ModelPropertiesSynchronizer(modelNodeId, model, cloudRepository).syncUsedLanguagesAndDevKitsFromMPS(); + } + + public void syncModelImportsFromMPS() { + new ModelPropertiesSynchronizer(modelNodeId, model, cloudRepository).syncModelImportsFromMPS(); + } + + protected SNode getOrCreateMPSNode(final long nodeId, final ITree tree) { + if (nodeId == 0L || nodeId == ITree.ROOT_ID) { + throw new RuntimeException("Invalid ID " + nodeId); + } + return nodeMap.getOrCreateNode(nodeId, new _FunctionTypes._return_P0_E0() { + public SAbstractConcept invoke() { + IConcept concept = tree.getConcept(nodeId); + if (concept == null) { + throw new RuntimeException("Node has no concept: " + nodeId); + } + SAbstractConcept sconcept = SConceptAdapter.unwrap(concept); + if (sconcept == null) { + throw new RuntimeException("Node has no MPS concept: " + nodeId + ", " + concept); + } + return sconcept; + } + }); + } + + public void syncNodeToMPS(long nodeId, ITree tree, boolean includeDescendants) { + if (LOG.isTraceEnabled()) { + LOG.trace("syncNode nodeId: " + nodeId); + } + try { + final SAbstractConcept concept = SConceptAdapter.unwrap(tree.getConcept(nodeId)); + + if (concept == null) { + throw new RuntimeException("Node has no concept: " + Long.toHexString(nodeId) + ". Role: " + tree.getRole(nodeId) + ", Concept: " + tree.getConcept(nodeId)); + } + SNode node = nodeMap.getOrCreateNode(nodeId, new _FunctionTypes._return_P0_E0() { + public SAbstractConcept invoke() { + return concept; + } + }); + for (SProperty property : CollectionSequence.fromCollection(concept.getProperties())) { + node.setProperty(property, tree.getProperty(nodeId, property.getName())); + } + for (SReferenceLink link : CollectionSequence.fromCollection(concept.getReferenceLinks())) { + syncReferenceToMPS(nodeId, link.getName(), tree); + } + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to sync node " + nodeId, ex); + } + } + syncChildrenToMPS(nodeId, tree, includeDescendants); + } + + public void syncPropertyToMPS(long nodeId, String role, ITree tree) { + SAbstractConcept concept = SConceptAdapter.unwrap(tree.getConcept(nodeId)); + SNode mpsNode = getOrCreateMPSNode(nodeId, tree); + SProperty mpsProperty = findProperty(concept, role); + mpsNode.setProperty(mpsProperty, tree.getProperty(nodeId, role)); + } + + public void syncProperties(INode source, INode target) { + for (IProperty property : ListSequence.fromList(target.getConcept().getAllProperties())) { + target.setPropertyValue(property.getName(), source.getPropertyValue(property.getName())); + } + } + + public void syncReferenceToMPS(final long nodeId, final String role, final ITree tree) { + pendingReferences.add(new _FunctionTypes._return_P0_E0() { + public SNode invoke() { + try { + SNode node = getOrCreateMPSNode(nodeId, tree); + INodeReference target = tree.getReferenceTarget(nodeId, role); + + SRepository repo = model.getRepository(); + IArea resolveContext = null; + if (repo == null) { + // We look in NodeMap instead + resolveContext = new CompositeArea(new PArea(getBranch()), nodeMap); + } else { + resolveContext = new CompositeArea(new PArea(getBranch()), new MPSArea(repo), nodeMap); + } + INode targetNode = check_l95w85_a0g0a0a0a0a14(target, resolveContext); + SNode targetSNode; + PNodeAdapter targetAsPNodeAdapter = null; + if (targetNode != null) { + targetNode = NodeUtilKt.deepUnwrapNode(targetNode); + } + if (targetNode instanceof PNodeAdapter) { + targetAsPNodeAdapter = (PNodeAdapter) targetNode; + } + if (targetAsPNodeAdapter == null) { + targetSNode = NodeToSNodeAdapter.wrap(targetNode, repo); + } else { + long targetId = (targetAsPNodeAdapter == null ? 0L : targetAsPNodeAdapter.getNodeId()); + targetSNode = (targetId == 0L ? null : getOrCreateMPSNode(targetId, tree)); + } + SReferenceLink link = findReferenceLink(node.getConcept(), role); + node.setReferenceTarget(link, targetSNode); + return targetSNode; + } catch (RuntimeException e) { + throw new RuntimeException("issue in syncReference, nodeId " + nodeId + ", role " + role, e); + } + } + }); + } + + public void syncChildrenToMPS(long nodeId, ITree tree, boolean includeDescendants) { + for (String linkName : tree.getChildRoles(nodeId)) { + syncChildrenToMPS(nodeId, linkName, tree, includeDescendants); + } + } + + public void syncChildrenToMPS(final long parentId, final String role, ITree tree, boolean includeDescendants) { + if (LOG.isTraceEnabled()) { + LOG.trace("syncChildren nodeId:" + parentId + ", role:" + role + ", descendants? " + includeDescendants); + } + Map syncedNodes = createChildrenSynchronizer(parentId, role).syncToMPS(tree); + + // order + boolean isRootNodes = parentId == modelNodeId && Objects.equals(role, LINKS.rootNodes$jxXY.getName()); + if (!(isRootNodes)) { + SNode parentNode = nodeMap.getNode(parentId); + SContainmentLink link = findContainmentLink(SNodeOperations.getConcept(parentNode), role); + int index = 0; + for (Long expectedId : Sequence.fromIterable(IterableUtil.asIterable(tree.getChildren(parentId, role).iterator()))) { + SNode expectedNode = nodeMap.getNode(expectedId); + SNode actualNode = ListSequence.fromList(SNodeOperations.getChildren(parentNode, link)).getElement(index); + if (!(Objects.equals(actualNode, expectedNode))) { + SNodeOperations.deleteNode(expectedNode); + ListSequence.fromList(SNodeOperations.getChildren(parentNode, link)).insertElement(index, expectedNode); + } + index++; + } + } + + if (includeDescendants) { + for (long childCloudId : MapSequence.fromMap(syncedNodes).keySet()) { + syncNodeToMPS(childCloudId, tree, includeDescendants); + } + } + } + + private Synchronizer createChildrenSynchronizer(final long parentId, final String role) { + return new Synchronizer(parentId, role) { + @Override + public Map associate(ITree tree, List cloudChildren, List mpsChildren, SyncDirection direction) { + final Map mpsIdToNode = MapSequence.fromMap(new HashMap()); + ListSequence.fromList(mpsChildren).visitAll(new IVisitor() { + public void visit(SNode it) { + MapSequence.fromMap(mpsIdToNode).put(it.getNodeId().toString(), it); + } + }); + Set mpsChildrenSet = SetSequence.fromSetWithValues(new HashSet(), mpsChildren); + Set cloudChildrenSet = SetSequence.fromSetWithValues(new HashSet(), cloudChildren); + + Map mapping = MapSequence.fromMap(new HashMap()); + for (long cloudChild : cloudChildren) { + SNode mpsChild = nodeMap.getNode(cloudChild); + if (mpsChild == null) { + String persistedMpsId = tree.getProperty(cloudChild, MPS_NODE_ID_PROPERTY_NAME); + if (persistedMpsId != null) { + mpsChild = MapSequence.fromMap(mpsIdToNode).get(persistedMpsId); + nodeMap.put(cloudChild, mpsChild); + } + } + if (mpsChild != null && SetSequence.fromSet(mpsChildrenSet).contains(mpsChild)) { + MapSequence.fromMap(mapping).put(cloudChild, mpsChild); + } + } + for (SNode mpsChild : ListSequence.fromList(mpsChildren)) { + long cloudChild = nodeMap.getId(mpsChild); + if (cloudChild != 0L && tree.containsNode(cloudChild) && SetSequence.fromSet(cloudChildrenSet).contains(cloudChild)) { + MapSequence.fromMap(mapping).put(cloudChild, mpsChild); + } + } + return mapping; + } + @Override + public long createCloudChild(IWriteTransaction t, SNode mpsChild) { + long nodeId = getOrCreateCloudNode(mpsChild, parentId, role); + if (t.getParent(nodeId) != parentId || t.getRole(nodeId) != role) { + t.moveChild(parentId, role, -1, nodeId); + } + return nodeId; + } + @Override + protected SNode createMPSChild(ITree tree, long cloudChildId) { + SNode newNode = getOrCreateMPSNode(cloudChildId, tree); + if (isRootNodes()) { + model.addRootNode(newNode); + } else { + SNode parentMPSNode = nodeMap.getNode(tree.getParent(cloudChildId)); + ListSequence.fromList(SNodeOperations.getChildren(parentMPSNode, findContainmentLink(SNodeOperations.getConcept(parentMPSNode), role))).addElement(newNode); + } + return newNode; + } + @Override + protected Iterable getMPSChildren() { + if (isRootNodes()) { + return model.getRootNodes(); + } else { + SNode parentNode = nodeMap.getNode(parentId); + if (parentNode == null) { + throw new IllegalStateException("Node has no parent but it is not a root node"); + } + Iterable children = parentNode.getChildren(findContainmentLink(parentNode.getConcept(), role)); + return Sequence.fromIterable(children).ofType(SNode.class); + } + } + private boolean isRootNodes() { + return parentId == modelNodeId && Objects.equals(role, LINKS.rootNodes$jxXY.getName()); + } + @Override + public void removeMPSChild(SNode mpsChild) { + SNodeOperations.deleteNode(mpsChild); + } + }; + } + + public SContainmentLink findContainmentLink(SAbstractConcept concept, final String linkName) { + Iterable links = concept.getContainmentLinks(); + SContainmentLink link = Sequence.fromIterable(links).findFirst(new IWhereFilter() { + public boolean accept(SContainmentLink it) { + return Objects.equals(it.getName(), linkName); + } + }); + if (link == null) { + throw new RuntimeException(concept + "." + linkName + " not found"); + } + return link; + } + public SReferenceLink findReferenceLink(SAbstractConcept concept, final String linkName) { + Iterable links = concept.getReferenceLinks(); + SReferenceLink link = Sequence.fromIterable(links).findFirst(new IWhereFilter() { + public boolean accept(SReferenceLink it) { + return Objects.equals(it.getName(), linkName); + } + }); + if (link == null) { + throw new RuntimeException(concept + "." + linkName + " not found"); + } + return link; + } + public SProperty findProperty(SAbstractConcept concept, final String role) { + Iterable properties = concept.getProperties(); + SProperty property = Sequence.fromIterable(properties).findFirst(new IWhereFilter() { + public boolean accept(SProperty it) { + return Objects.equals(it.getName(), role); + } + }); + if (property == null) { + throw new RuntimeException(concept + "." + role + " not found"); + } + return property; + } + + public void syncNodeFromMPS(final SNode parentNode, boolean includeDescendants) { + if (parentNode.getModel() != model) { + throw new RuntimeException("Not part of this model: " + parentNode); + } + final IBranch branch = getBranch(); + final IWriteTransaction t = branch.getWriteTransaction(); + final SConcept concept = parentNode.getConcept(); + + final long parentNodeId = getOrCreateCloudNode(parentNode); + + INode cloudNode = new PNodeAdapter(parentNodeId, branch); + MPSNodeMapping.mapToMpsNode(cloudNode, parentNode); + + for (SProperty property : CollectionSequence.fromCollection(concept.getProperties())) { + String oldValue = t.getProperty(parentNodeId, property.getName()); + String newValue = parentNode.getProperty(property); + if (!(Objects.equals(newValue, oldValue))) { + t.setProperty(parentNodeId, property.getName(), newValue); + } + } + + for (final SReferenceLink link : CollectionSequence.fromCollection(concept.getReferenceLinks())) { + pendingReferences.add(new _FunctionTypes._return_P0_E0() { + public SNode invoke() { + SNode targetSNode = parentNode.getReferenceTarget(link); + INodeReference currentTarget = t.getReferenceTarget(parentNodeId, link.getName()); + if (targetSNode == null) { + if (currentTarget != null) { + t.setReferenceTarget(parentNodeId, link.getName(), null); + } + } else { + long targetId = nodeMap.getId(targetSNode); + INode targetNode; + if (targetId == 0L || !(t.containsNode(targetId))) { + targetNode = SNodeToNodeAdapter.wrap(targetSNode); + } else { + targetNode = new PNodeAdapter(targetId, branch); + } + if (!(Objects.equals(currentTarget, targetNode.getReference()))) { + t.setReferenceTarget(parentNodeId, link.getName(), targetNode.getReference()); + } + } + return (SNode) null; + } + }); + } + + for (SContainmentLink link : CollectionSequence.fromCollection(concept.getContainmentLinks())) { + syncChildrenFromMPS(link, t, parentNodeId, parentNode, includeDescendants); + } + } + + protected void syncChildrenFromMPS(SContainmentLink link, IWriteTransaction t, long parentNodeId, SNode parentNode, boolean includeDescendants) { + Map syncedNodes = createChildrenSynchronizer(parentNodeId, link.getName()).syncToCloud(t); + + // order + Iterable> sortedMappings = MapSequence.fromMap(syncedNodes).sort(new ISelector, Integer>() { + public Integer select(IMapping it) { + SNode mpsNode = it.value(); + return SNodeOperations.getIndexInParent(mpsNode); + } + }, true); + int index = 0; + for (IMapping mapping : Sequence.fromIterable(sortedMappings)) { + long cloudId = mapping.key(); + Iterable children = t.getChildren(parentNodeId, link.getName()); + long actualId = Optional.ofNullable(Sequence.fromIterable(children).skip(1).first()).orElse(0L); + if (actualId != cloudId) { + t.moveChild(parentNodeId, link.getName(), index, cloudId); + } + index++; + } + + if (includeDescendants) { + for (SNode childNode : Sequence.fromIterable(MapSequence.fromMap(syncedNodes).values())) { + syncNodeFromMPS(childNode, includeDescendants); + } + } + } + + protected long getOrCreateCloudNode(SNode node, long parentIfCreate, String roleIfCreate) { + long nodeId = nodeMap.getId(node); + IWriteTransaction t = getBranch().getWriteTransaction(); + if (nodeId == 0L || !(t.containsNode(nodeId))) { + nodeId = t.addNewChild(parentIfCreate, roleIfCreate, -1, SConceptAdapter.wrap(node.getConcept())); + nodeMap.put(nodeId, node); + } + return nodeId; + } + + protected long getOrCreateCloudNode(SNode node) { + return getOrCreateCloudNode(node, ITree.ROOT_ID, ITree.DETACHED_NODES_ROLE); + } + + public long getCloudNodeId(SNode node) { + return nodeMap.getId(node); + } + + public long getOrSyncToCloud(SNode node, IWriteTransaction t) { + long cloudId = nodeMap.getId(node); + if (cloudId == 0L || !(t.containsNode(cloudId))) { + SNode parent = node.getParent(); + if (parent == null) { + syncRootNodesFromMPS(); + } else { + long parentCloudId = getOrSyncToCloud(parent, t); + syncNodeFromMPS(parent, true); + } + cloudId = nodeMap.getId(node); + } + return cloudId; + } + + public void handleMPSNodeAdded(@NotNull final SNodeAddEvent e) { + new PArea(getBranch()).executeWrite(new Function0() { + public Unit invoke() { + pendingReferences.runAndFlush(new Runnable() { + public void run() { + IWriteTransaction t = getBranch().getWriteTransaction(); + long parentId; + String role; + if (e.isRoot()) { + parentId = modelNodeId; + role = LINKS.rootNodes$jxXY.getName(); + } else { + parentId = nodeMap.getId(e.getParent()); + role = e.getAggregationLink().getName(); + } + if (parentId == 0L || !(t.containsNode(parentId))) { + return; + } + SNode child = e.getChild(); + if (e.isRoot()) { + long childId = nodeMap.getId(child); + if (childId == 0L || !(t.containsNode(childId))) { + childId = t.addNewChild(parentId, role, -1, SConceptAdapter.wrap(SNodeOperations.getConcept(child))); + nodeMap.put(childId, child); + } else { + t.moveChild(parentId, role, -1, childId); + } + } else { + syncChildrenFromMPS(e.getAggregationLink(), t, parentId, e.getParent(), false); + } + syncNodeFromMPS(child, true); + } + }); + return Unit.INSTANCE; + } + }); + } + + public void handleMPSNodeRemoved(@NotNull final SNodeRemoveEvent e) { + final IBranch branch = getBranch(); + new PArea(branch).executeWrite(new Function0() { + public Unit invoke() { + IWriteTransaction t = branch.getWriteTransaction(); + long childId = nodeMap.getId(e.getChild()); + if (childId != 0L && t.containsNode(childId)) { + t.moveChild(ITree.ROOT_ID, ITree.DETACHED_NODES_ROLE, -1, childId); + } + return Unit.INSTANCE; + } + }); + } + + public void handleReferenceChanged(@NotNull final SReferenceChangeEvent e) { + final IBranch branch = getBranch(); + new PArea(branch).executeWrite(new Function0() { + public Unit invoke() { + IWriteTransaction t = getBranch().getWriteTransaction(); + SNode targetSNode = check_l95w85_a0b0a0a1a96(e.getNewValue()); + long sourceId = getOrCreateCloudNode(e.getNode()); + if (targetSNode == null) { + t.setReferenceTarget(sourceId, e.getAssociationLink().getName(), null); + } else { + long targetId = nodeMap.getId(targetSNode); + INode targetNode; + if (targetId == 0L || !(t.containsNode(targetId))) { + targetNode = SNodeToNodeAdapter.wrap(targetSNode); + } else { + targetNode = new PNodeAdapter(targetId, branch); + } + t.setReferenceTarget(sourceId, e.getAssociationLink().getName(), targetNode.getReference()); + } + return Unit.INSTANCE; + } + }); + } + + public class PendingReferences { + protected List<_FunctionTypes._return_P0_E0> currentReferences; + + public synchronized void runAndFlush(Runnable runnable) { + if (currentReferences == null) { + try { + currentReferences = ListSequence.fromList(new ArrayList<_FunctionTypes._return_P0_E0>()); + runnable.run(); + } finally { + try { + processPendingReferences(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to process pending reference", ex); + } + } + currentReferences = null; + } + } else { + runnable.run(); + } + } + + public synchronized void add(_FunctionTypes._return_P0_E0 ref) { + if (currentReferences == null) { + throw new IllegalStateException("Call runAndFlush first"); + } + ListSequence.fromList(currentReferences).addElement(ref); + } + + protected void processPendingReferences() { + Set targetModels = SetSequence.fromSet(new HashSet()); + for (_FunctionTypes._return_P0_E0 r : ListSequence.fromList(currentReferences)) { + try { + SNode targetNode = r.invoke(); + SetSequence.fromSet(targetModels).addElement(check_l95w85_a0a1a0a1a6tc(targetNode)); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + + Iterable modelsToImport = SetSequence.fromSet(targetModels).where(new IWhereFilter() { + public boolean accept(SModel it) { + return it != null && it != model; + } + }); + if (Sequence.fromIterable(modelsToImport).isNotEmpty()) { + final ModelImporter importer = new ModelImporter(model); + Sequence.fromIterable(modelsToImport).visitAll(new IVisitor() { + public void visit(SModel it) { + importer.prepare(it.getReference()); + } + }); + importer.execute(); + } + } + + } + private static INode check_l95w85_a0g0a0a0a0a14(INodeReference checkedDotOperand, IArea resolveContext) { + if (null != checkedDotOperand) { + return checkedDotOperand.resolveNode(resolveContext); + } + return null; + } + private static SNode check_l95w85_a0b0a0a1a96(SReference checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getTargetNode(); + } + return null; + } + private static SModel check_l95w85_a0a1a0a1a6tc(SNode checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModel(); + } + return null; + } + + private static final class LINKS { + /*package*/ static final SContainmentLink rootNodes$jxXY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x69652614fd1c514L, "rootNodes"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelixNotifications.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelixNotifications.java new file mode 100644 index 00000000..e955da06 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelixNotifications.java @@ -0,0 +1,23 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import com.intellij.notification.Notifications; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import jetbrains.mps.project.MPSProject; +import jetbrains.mps.ide.project.ProjectHelper; + +public class ModelixNotifications { + private static final String GROUP_ID = "modelix"; + public static void notifyWarning(String title, String message) { + Notifications.Bus.notify(new Notification(GROUP_ID, title, message, NotificationType.WARNING)); + } + + public static void notifyError(String title, String message) { + Notifications.Bus.notify(new Notification(GROUP_ID, title, message, NotificationType.ERROR)); + } + public static void notifyError(String title, String message, MPSProject mpsProject) { + Notifications.Bus.notify(new Notification(GROUP_ID, title, message, NotificationType.ERROR), ProjectHelper.toIdeaProject(mpsProject)); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelsSynchronizer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelsSynchronizer.java new file mode 100644 index 00000000..47ed2da7 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModelsSynchronizer.java @@ -0,0 +1,136 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import org.modelix.model.api.ITree; +import org.jetbrains.mps.openapi.model.SModelId; +import jetbrains.mps.model.ModelDeleteHelper; +import java.util.Map; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Objects; +import org.jetbrains.mps.openapi.persistence.PersistenceFacade; +import org.modelix.model.api.IWriteTransaction; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import jetbrains.mps.project.Project; +import jetbrains.mps.project.ProjectManager; +import jetbrains.mps.lang.migration.runtime.base.VersionFixer; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SConcept; + +public class ModelsSynchronizer extends Synchronizer { + + private SModule module; + + public ModelsSynchronizer(long cloudParentId, SModule module) { + super(cloudParentId, LINKS.models$h3QT.getName()); + this.module = module; + } + + public SModule getModule() { + return module; + } + + @Override + protected Iterable getMPSChildren() { + return ListSequence.fromList(SModuleUtils.getModelsWithoutDescriptor(module)).where(new IWhereFilter() { + public boolean accept(SModel it) { + return !(it.isReadOnly()); + } + }); + } + + @Override + protected SModel createMPSChild(ITree tree, long cloudChildId) { + SModelId id = getModelId(tree, cloudChildId); + if (id == null) { + id = jetbrains.mps.smodel.SModelId.foreign("cloud-" + cloudChildId); + } + String name = tree.getProperty(cloudChildId, PROPS.name$MnvL.getName()); + return createModel(name, id, cloudChildId); + } + + protected SModel createModel(String name, SModelId id, long modelNodeId) { + return SModuleUtils.createModel(module, name, id); + } + + @Override + public void removeMPSChild(SModel mpsChild) { + new ModelDeleteHelper(mpsChild).delete(); + } + + @Override + public Map associate(ITree tree, List cloudChildren, List mpsChildren, SyncDirection direction) { + Map result = MapSequence.fromMap(new HashMap()); + List availableModels = ListSequence.fromListWithValues(new ArrayList(), mpsChildren); + + for (long cloudModelId : cloudChildren) { + SModelId id = getModelId(tree, cloudModelId); + String name = tree.getProperty(cloudModelId, PROPS.name$MnvL.getName()); + + // There can be models with duplicate names. That's why we can't just search in a map. + Iterator itr = ListSequence.fromList(availableModels).iterator(); + while (itr.hasNext()) { + SModel it = itr.next(); + if (id != null && Objects.equals(it.getModelId(), id) || Objects.equals(it.getName().getValue(), name)) { + MapSequence.fromMap(result).put(cloudModelId, it); + itr.remove(); + break; + } + } + } + + return result; + } + + protected SModelId getModelId(ITree tree, long cloudModelId) { + String serializedId = tree.getProperty(cloudModelId, PROPS.id$lDUo.getName()); + if ((serializedId == null || serializedId.length() == 0)) { + return null; + } + return PersistenceFacade.getInstance().createModelId(serializedId); + } + + @Override + public long createCloudChild(IWriteTransaction t, SModel mpsChild) { + long modelNodeId = t.addNewChild(getCloudParentId(), LINKS.models$h3QT.getName(), -1, SConceptAdapter.wrap(CONCEPTS.Model$2P)); + t.setProperty(modelNodeId, PROPS.id$lDUo.getName(), mpsChild.getModelId().toString()); + t.setProperty(modelNodeId, PROPS.name$MnvL.getName(), mpsChild.getName().getValue()); + return modelNodeId; + } + + + @Override + public Map syncToMPS(ITree tree) { + Map result = super.syncToMPS(tree); + + List projects = ProjectManager.getInstance().getOpenedProjects(); + if (ListSequence.fromList(projects).isNotEmpty()) { + new VersionFixer(ListSequence.fromList(projects).first(), module, true).updateImportVersions(); + } + + return result; + } + + private static final class LINKS { + /*package*/ static final SContainmentLink models$h3QT = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x69652614fd1c512L, "models"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$lDUo = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x244b85440ee67212L, "id"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Model$2P = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, "org.modelix.model.repositoryconcepts.structure.Model"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleBinding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleBinding.java new file mode 100644 index 00000000..e959129e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleBinding.java @@ -0,0 +1,170 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.model.api.ITreeChangeVisitor; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.mps.openapi.module.SModuleListenerBase; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.model.SModel; +import org.apache.log4j.Level; +import org.jetbrains.mps.openapi.model.SModelReference; +import org.modelix.model.api.ITree; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.internal.collections.runtime.Sequence; +import java.util.Map; +import org.modelix.model.api.IWriteTransaction; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import jetbrains.mps.internal.collections.runtime.ListSequence; + +public abstract class ModuleBinding extends Binding { + private static final Logger LOG = LogManager.getLogger(ModuleBinding.class); + protected final long moduleNodeId; + private ITreeChangeVisitor treeChangeVisitor = new ITreeChangeVisitor() { + @Override + public void childrenChanged(long nodeId, @Nullable String role) { + assertSyncThread(); + if (nodeId == ModuleBinding.this.moduleNodeId) { + enqueueSync(SyncDirection.TO_MPS, false, null); + } + } + @Override + public void containmentChanged(long nodeId) { + } + @Override + public void referenceChanged(long nodeId, String role) { + } + @Override + public void propertyChanged(long nodeId, String role) { + } + }; + private SModuleListenerBase moduleListener = new SModuleListenerBase() { + @Override + public void modelAdded(SModule module, SModel model) { + try { + enqueueSync(SyncDirection.TO_CLOUD, false, null); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + @Override + public void modelRemoved(SModule module, SModelReference ref) { + try { + enqueueSync(SyncDirection.TO_CLOUD, false, null); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + @Override + public void modelRenamed(SModule module, SModel model, SModelReference oldRef) { + try { + enqueueSync(SyncDirection.TO_CLOUD, false, null); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + }; + + public ModuleBinding(long moduleNodeId, SyncDirection initialSyncDirection) { + super(initialSyncDirection); + this.moduleNodeId = moduleNodeId; + } + + @Override + public String toString() { + return "Module: " + Long.toHexString(moduleNodeId) + " -> " + check_rpydrg_a0a0g(getModule(), this); + } + + public abstract SModule getModule(); + + @Nullable + @Override + protected ITreeChangeVisitor getTreeChangeVisitor(final ITree oldTree, final ITree newTree) { + return treeChangeVisitor; + } + + @Override + protected void doActivate() { + getModule().addModuleListener(moduleListener); + if (getRootBinding().getSyncQueue().getTask(this) == null) { + enqueueSync((initialSyncDirection == null ? SyncDirection.TO_MPS : initialSyncDirection), true, null); + } + } + + @Override + protected void doDeactivate() { + getModule().removeModuleListener(moduleListener); + } + + @Override + protected void doSyncToMPS(@NotNull ITree tree) { + if (runningTask.isInitialSync && Sequence.fromIterable(getModelsSynchronizer().getMPSChildren()).isNotEmpty() && Sequence.fromIterable(getModelsSynchronizer().getCloudChildren(tree)).isEmpty()) { + // TODO remove this workaround + forceEnqueueSyncTo(SyncDirection.TO_CLOUD, true, null); + return; + } + + Map mappings = getModelsSynchronizer().syncToMPS(tree); + updateBindings(mappings, SyncDirection.TO_MPS); + } + + @Override + public void doSyncToCloud(IWriteTransaction t) { + Map mappings = getModelsSynchronizer().syncToCloud(t); + updateBindings(mappings, SyncDirection.TO_CLOUD); + } + + private void updateBindings(final Map mappings, final SyncDirection syncDirection) { + final Map bindings = MapSequence.fromMap(new HashMap()); + Sequence.fromIterable(getOwnedBindings()).ofType(ModelBinding.class).visitAll(new IVisitor() { + public void visit(ModelBinding it) { + MapSequence.fromMap(bindings).put(it.getModelNodeId(), it); + } + }); + + List toAdd = SetSequence.fromSet(MapSequence.fromMap(mappings).keySet()).subtract(SetSequence.fromSet(MapSequence.fromMap(bindings).keySet())).toListSequence(); + List toRemove = SetSequence.fromSet(MapSequence.fromMap(bindings).keySet()).subtract(SetSequence.fromSet(MapSequence.fromMap(mappings).keySet())).toListSequence(); + + ListSequence.fromList(toRemove).visitAll(new IVisitor() { + public void visit(Long it) { + ModelBinding binding = MapSequence.fromMap(bindings).get(it); + binding.deactivate(null); + binding.setOwner(null); + } + }); + + ListSequence.fromList(toAdd).visitAll(new IVisitor() { + public void visit(Long it) { + ModelBinding binding = new ModelBinding(it, MapSequence.fromMap(mappings).get(it), syncDirection); + binding.setOwner(ModuleBinding.this); + binding.activate(null); + } + }); + } + + protected Synchronizer getModelsSynchronizer() { + return new ModelsSynchronizer(moduleNodeId, getModule()); + } + + public long getModuleNodeId() { + return this.moduleNodeId; + } + private static String check_rpydrg_a0a0g(SModule checkedDotOperand, ModuleBinding checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModuleName(); + } + return null; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleCheckout.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleCheckout.java new file mode 100644 index 00000000..f3e2e9bc --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleCheckout.java @@ -0,0 +1,55 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import jetbrains.mps.project.Project; +import jetbrains.mps.project.Solution; +import org.modelix.model.api.PNodeAdapter; +import java.util.Set; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import java.util.List; +import javax.swing.SwingUtilities; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import jetbrains.mps.internal.collections.runtime.ListSequence; + +public class ModuleCheckout { + + private CloudRepository treeInRepository; + private Project mpsProject; + + public ModuleCheckout(Project mpsProject, CloudRepository treeInRepository) { + this.mpsProject = mpsProject; + this.treeInRepository = treeInRepository; + } + + public Solution checkoutCloudModule(PNodeAdapter cloudModule) { + final ModelCloudExporter modelCloudExporter = new ModelCloudExporter(treeInRepository); + modelCloudExporter.setCheckoutMode(); + final String exportPath = mpsProject.getProjectFile().getAbsolutePath(); + final Set moduleIds = SetSequence.fromSetAndArray(new HashSet(), cloudModule.getNodeId()); + final Wrappers._T> solutions = new Wrappers._T>(); + + Runnable r = new Runnable() { + @Override + public void run() { + mpsProject.getRepository().getModelAccess().executeCommand(new Runnable() { + public void run() { + solutions.value = modelCloudExporter.export(exportPath, moduleIds, mpsProject); + } + }); + } + }; + if (SwingUtilities.isEventDispatchThread()) { + r.run(); + } else { + ApplicationManager.getApplication().invokeAndWait(r, ModalityState.NON_MODAL); + } + if (ListSequence.fromList(solutions.value).count() != 1) { + throw new RuntimeException("One solution expected. These found: " + solutions.value); + } + return ListSequence.fromList(solutions.value).getElement(0); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleUtils.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleUtils.java new file mode 100644 index 00000000..0ba310e4 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ModuleUtils.java @@ -0,0 +1,24 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.model.SModel; +import jetbrains.mps.internal.collections.runtime.ListSequence; + +public class ModuleUtils { + public ModuleUtils() { + } + public static void printModulesNames(final SModule _this, String comment) { + StringBuilder sb = new StringBuilder(); + boolean empty = true; + for (SModel m : ListSequence.fromList(SModuleUtils.getModelsWithoutDescriptor(_this))) { + if (empty) { + empty = false; + } else { + sb.append(", "); + } + sb.append(m.getModelName()); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MpsReplicatedRepository.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MpsReplicatedRepository.java new file mode 100644 index 00000000..dd7c6787 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/MpsReplicatedRepository.java @@ -0,0 +1,140 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.client.ReplicatedRepository; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import java.util.Set; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.apache.log4j.Level; +import com.intellij.openapi.command.undo.DocumentReference; +import org.jetbrains.mps.openapi.repository.CommandListener; +import org.modelix.model.lazy.CLVersion; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.undo.UndoManager; +import org.modelix.model.client.IModelClient; +import org.modelix.model.lazy.RepositoryId; +import org.jetbrains.annotations.NotNull; +import java.util.function.Supplier; +import kotlin.jvm.functions.Function0; +import jetbrains.mps.smodel.MPSModuleRepository; +import com.intellij.openapi.command.undo.UndoableAction; +import jetbrains.mps.internal.collections.runtime.Sequence; +import com.intellij.openapi.command.undo.UnexpectedUndoException; +import org.modelix.model.area.PArea; +import kotlin.Unit; +import org.modelix.model.operations.OTWriteTransactionKt; +import org.modelix.model.operations.UndoOp; +import org.modelix.model.lazy.KVEntryReference; +import org.modelix.model.persistent.CPVersion; + +public class MpsReplicatedRepository extends ReplicatedRepository { + private static final Logger LOG = LogManager.getLogger(MpsReplicatedRepository.class); + + private static final Set INSTANCES = SetSequence.fromSet(new HashSet()); + + public static void disposeAll() { + List list; + synchronized (INSTANCES) { + list = ListSequence.fromListWithValues(new ArrayList(), INSTANCES); + } + for (MpsReplicatedRepository instance : ListSequence.fromList(list)) { + try { + instance.dispose(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + } + + private static Set affectedDocuments = SetSequence.fromSet(new HashSet()); + + public static void documentChanged(DocumentReference doc) { + SetSequence.fromSet(affectedDocuments).addElement(doc); + } + + private CommandListener commandListener = new CommandListener() { + @Override + public void commandStarted() { + SetSequence.fromSet(affectedDocuments).clear(); + startEdit(); + } + + @Override + public void commandFinished() { + CLVersion version = endEdit(); + if (version == null) { + return; + } + Project project = CommandProcessor.getInstance().getCurrentCommandProject(); + if (project == null) { + return; + } + UndoManager undoManager = UndoManager.getInstance(project); + undoManager.undoableActionPerformed(new ModelixUndoableAction(version, affectedDocuments)); + } + }; + + public MpsReplicatedRepository(final IModelClient client, final RepositoryId repositoryId, @NotNull final String branchName, final Supplier user) { + super(client, repositoryId, branchName, new Function0() { + @Override + public String invoke() { + return user.get(); + } + }); + MPSModuleRepository.getInstance().getModelAccess().addCommandListener(commandListener); + synchronized (INSTANCES) { + SetSequence.fromSet(INSTANCES).addElement(this); + } + } + + public void dispose() { + synchronized (INSTANCES) { + SetSequence.fromSet(INSTANCES).removeElement(this); + } + if (isDisposed()) { + return; + } + MPSModuleRepository.getInstance().getModelAccess().removeCommandListener(commandListener); + super.dispose(); + } + + public class ModelixUndoableAction implements UndoableAction { + private CLVersion version; + private DocumentReference[] documents; + public ModelixUndoableAction(CLVersion version, Iterable docs) { + this.version = version; + this.documents = Sequence.fromIterable(docs).toGenericArray(DocumentReference.class); + } + @Override + public void undo() throws UnexpectedUndoException { + new PArea(getBranch()).executeWrite(new Function0() { + @Override + public Unit invoke() { + OTWriteTransactionKt.applyOperation(getBranch().getWriteTransaction(), new UndoOp(new KVEntryReference(version.getData()))); + return Unit.INSTANCE; + } + }); + } + @Override + public void redo() throws UnexpectedUndoException { + throw new UnexpectedUndoException("Not supported yet"); + } + @Override + public DocumentReference[] getAffectedDocuments() { + return (documents.length == 0 ? null : documents); + } + @Override + public boolean isGlobal() { + return documents.length == 0; + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/NodeMap.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/NodeMap.java new file mode 100644 index 00000000..e05d6100 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/NodeMap.java @@ -0,0 +1,165 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.area.AbstractArea; +import org.modelix.model.area.IAreaReference; +import org.modelix.model.api.IBranch; +import gnu.trove.map.TLongObjectMap; +import org.jetbrains.mps.openapi.model.SNode; +import gnu.trove.map.hash.TLongObjectHashMap; +import gnu.trove.map.TObjectLongMap; +import gnu.trove.map.hash.TObjectLongHashMap; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.IConcept; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.api.IConceptReference; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.jetbrains.mps.openapi.model.SNodeId; +import org.modelix.model.api.INode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import org.jetbrains.mps.openapi.persistence.PersistenceFacade; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.mps.openapi.language.SInterfaceConcept; +import jetbrains.mps.smodel.adapter.MetaAdapterByDeclaration; +import org.modelix.model.api.INodeReference; +import org.modelix.model.mpsadapters.mps.SNodeReferenceAdapter; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.Objects; +import org.modelix.model.mpsadapters.mps.SNodeToNodeAdapter; + +public class NodeMap extends AbstractArea implements IAreaReference { + + @FunctionalInterface + public interface BranchProvider { + IBranch getBranch(); + } + + /** + * Map from Cloud ID to Node + */ + private TLongObjectMap id2node = new TLongObjectHashMap(); + /** + * Map from Node to Cloud ID + */ + private TObjectLongMap node2id = new TObjectLongHashMap(); + + private BranchProvider branchProvider; + + public NodeMap(BranchProvider branchProvider) { + this.branchProvider = branchProvider; + } + + @Nullable + @Override + public IConcept resolveConcept(@NotNull IConceptReference reference) { + return null; + } + + @NotNull + @Override + public IAreaReference getReference() { + return this; + } + + public void put(long id, SNode node) { + id2node.put(id, node); + node2id.put(node, id); + } + + public void removeId(long id) { + SNode node = id2node.remove(id); + if (node != null) { + node2id.remove(node); + } + } + + public void removeNode(SNode node) { + long id = node2id.remove(node); + id2node.remove(id); + } + + public SNode getNode(long id) { + return id2node.get(id); + } + + public long getId(SNode node) { + return node2id.get(node); + } + + public boolean hasMappingForCloudNode(long cloudID) { + return id2node.containsKey(cloudID); + } + + public SNode getOrCreateNode(long id, _FunctionTypes._return_P0_E0 conceptProducer) { + SNode node = getNode(id); + if (node == null) { + try { + // The id parameters is the ID of the node in the replicated data structure. + // We could use any ID for the MPS node, but for the load balancing to work properly, + // node references should be resolvable independent of the MPS instance. + SNodeId nodeId; + + // We need to get the associated MPS Node ID, stored in the INode + final INode iNode = new PNodeAdapter(id, branchProvider.getBranch()); + // We should probably store these values somewhere, to avoid transactions + String mpsNodeIdAsString = (branchProvider.getBranch().canRead() ? MPSNodeMapping.mappedMpsNodeID(iNode) : new PArea(branchProvider.getBranch()).executeRead(new Function0() { + public String invoke() { + return MPSNodeMapping.mappedMpsNodeID(iNode); + } + })); + + if (mpsNodeIdAsString == null) { + // Here, given we have no explicit NodeId in the INode, we use the id of the INode + // We may want to create a special SNodeId in this case? + nodeId = new jetbrains.mps.smodel.SNodeId.Regular(id); + } else { + nodeId = PersistenceFacade.getInstance().createNodeId(mpsNodeIdAsString); + } + Object rawConcept = conceptProducer.invoke(); + SConcept c; + if (rawConcept instanceof SInterfaceConcept) { + c = MetaAdapterByDeclaration.asInstanceConcept(((SAbstractConcept) rawConcept)); + } else if (rawConcept instanceof SConcept) { + c = (SConcept) rawConcept; + } else { + throw new RuntimeException("Concept producer returned something unexpected: " + rawConcept); + } + node = new jetbrains.mps.smodel.SNode(c, nodeId); + put(id, node); + } catch (RuntimeException e) { + throw new RuntimeException("Issue while trying to create node with id " + id + " and concept " + conceptProducer, e); + } + } + return node; + } + @Nullable + @Override + public INode resolveOriginalNode(@Nullable INodeReference reference) { + if (reference instanceof SNodeReferenceAdapter) { + SNodeReferenceAdapter sNodeReferenceAdapter = ((SNodeReferenceAdapter) reference); + final SNodeId targetNodeId = sNodeReferenceAdapter.getReference().getNodeId(); + Optional sNode = node2id.keySet().stream().filter(new Predicate() { + public boolean test(SNode sNode) { + return Objects.equals(sNode.getNodeId(), targetNodeId); + } + }).findFirst(); + if (sNode.isPresent()) { + return SNodeToNodeAdapter.wrap(sNode.get()); + } else { + return null; + } + } + return null; + } + + @NotNull + @Override + public INode getRoot() { + throw new UnsupportedOperationException(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/NonIndirectBranch.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/NonIndirectBranch.java new file mode 100644 index 00000000..117a0d0b --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/NonIndirectBranch.java @@ -0,0 +1,32 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.client.IIndirectBranch; +import org.modelix.model.api.IBranch; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.api.IBranchListener; + +public class NonIndirectBranch implements IIndirectBranch { + private IBranch branch; + + public NonIndirectBranch(IBranch branch) { + this.branch = branch; + } + + @Override + public void addListener(@NotNull IBranchListener listener) { + branch.addListener(listener); + } + + @NotNull + @Override + public IBranch getBranch() { + return branch; + } + + @Override + public void removeListener(@NotNull IBranchListener listener) { + branch.removeListener(listener); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/PNodeAdapterCreationMethods.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/PNodeAdapterCreationMethods.java new file mode 100644 index 00000000..3ec5d71b --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/PNodeAdapterCreationMethods.java @@ -0,0 +1,55 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import java.util.UUID; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.mps.openapi.language.SProperty; + +public class PNodeAdapterCreationMethods { + public PNodeAdapterCreationMethods() { + } + public static INode createModuleInRepository(final PNodeAdapter _this, final String name) { + // TODO check the concept of this node is Repository + return new PArea(_this.getBranch()).executeWrite(new Function0() { + public INode invoke() { + INode newModule = _this.addNewChild(LINKS.modules$jBPn.getName(), -1, SConceptAdapter.wrap(CONCEPTS.Module$4i)); + newModule.setPropertyValue(PROPS.name$MnvL.getName(), name); + newModule.setPropertyValue(PROPS.id$7MjP.getName(), UUID.randomUUID().toString()); + return newModule; + } + }); + } + public static INode createProject(final PNodeAdapter _this, final String name) { + // TODO check the concept of this node is Repository + return new PArea(_this.getBranch()).executeWrite(new Function0() { + public INode invoke() { + INode newModule = _this.addNewChild(LINKS.projects$NW07.getName(), -1, SConceptAdapter.wrap(CONCEPTS.Project$An)); + newModule.setPropertyValue(PROPS.name$MnvL.getName(), name); + return newModule; + } + }); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink modules$jBPn = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x69652614fd1c517L, "modules"); + /*package*/ static final SContainmentLink projects$NW07 = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c516L, 0x620a8558361d3e0cL, "projects"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + /*package*/ static final SConcept Project$An = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, "org.modelix.model.repositoryconcepts.structure.Project"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$7MjP = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x3aa34013f2a802e0L, "id"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/PhysicalToCloudModelMapping.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/PhysicalToCloudModelMapping.java new file mode 100644 index 00000000..1e285f5e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/PhysicalToCloudModelMapping.java @@ -0,0 +1,27 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SModel; +import org.modelix.model.api.INode; + +/** + * This represents just a pair of associated models: one physical and one on the cloud. + */ +public class PhysicalToCloudModelMapping { + private SModel physicalModel; + private INode cloudModel; + + public SModel getPhysicalModel() { + return physicalModel; + } + + public INode getCloudModel() { + return cloudModel; + } + + public PhysicalToCloudModelMapping(SModel physicalModel, INode cloudModel) { + this.physicalModel = physicalModel; + this.cloudModel = cloudModel; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectBinding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectBinding.java new file mode 100644 index 00000000..2937165a --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectBinding.java @@ -0,0 +1,215 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import jetbrains.mps.project.MPSProject; +import org.jetbrains.mps.openapi.module.SRepositoryListenerBase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.module.SModuleReference; +import org.modelix.model.api.IBranch; +import kotlin.jvm.functions.Function1; +import org.modelix.model.api.IWriteTransaction; +import kotlin.Unit; +import org.modelix.model.api.ITree; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.modelix.model.api.IReadTransaction; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.jetbrains.annotations.Nullable; +import org.modelix.model.api.ITreeChangeVisitor; +import java.util.Objects; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.IMapping; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import java.util.HashMap; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SContainmentLink; + +public class ProjectBinding extends Binding { + private static final Logger LOG = LogManager.getLogger(ProjectBinding.class); + + private long projectNodeId; + private MPSProject mpsProject; + private SRepositoryListenerBase repositoryListener = new SRepositoryListenerBase() { + @Override + public void moduleAdded(@NotNull SModule p1) { + enqueueSyncToCloud(); + } + + @Override + public void moduleRemoved(@NotNull SModuleReference p1) { + enqueueSyncToCloud(); + } + private void enqueueSyncToCloud() { + enqueueSync(SyncDirection.TO_CLOUD, false, null); + } + }; + + public ProjectBinding(MPSProject mpsProject, long projectNodeId, SyncDirection initialSyncDirection) { + super(initialSyncDirection); + this.mpsProject = mpsProject; + this.projectNodeId = projectNodeId; + if (LOG.isDebugEnabled()) { + LOG.debug("Project binding created: " + this); + } + } + + @Override + public String toString() { + return "Project: " + Long.toHexString(projectNodeId) + " -> " + mpsProject.getName(); + } + + public MPSProject getProject() { + return this.mpsProject; + } + + public long getProjectNodeId() { + return this.projectNodeId; + } + + @Override + protected void doActivate() { + if (LOG.isDebugEnabled()) { + LOG.debug("Activating: " + this); + } + final IBranch branch = getBranch(); + if (projectNodeId == 0L) { + mpsProject.getRepository().getModelAccess().runReadAction(new Runnable() { + public void run() { + branch.runWriteT(new Function1() { + public Unit invoke(IWriteTransaction t) { + projectNodeId = t.addNewChild(ITree.ROOT_ID, "projects", -1, SConceptAdapter.wrap(CONCEPTS.Project$An)); + t.setProperty(projectNodeId, PROPS.name$MnvL.getName(), mpsProject.getName()); + return Unit.INSTANCE; + } + }); + enqueueSync(SyncDirection.TO_CLOUD, true, null); + } + }); + } else { + boolean cloudProjectIsEmpty = branch.computeReadT(new Function1() { + public Boolean invoke(IReadTransaction t) { + Iterable children = t.getChildren(projectNodeId, LINKS.modules$Bi3g.getName()); + return Sequence.fromIterable(children).isEmpty(); + } + }); + if (cloudProjectIsEmpty) { + enqueueSync(SyncDirection.TO_CLOUD, true, null); + } else { + enqueueSync(SyncDirection.TO_MPS, true, null); + } + } + mpsProject.getRepository().addRepositoryListener(repositoryListener); + if (LOG.isDebugEnabled()) { + LOG.debug("Activated: " + this); + } + } + + @Override + protected void doDeactivate() { + mpsProject.getRepository().removeRepositoryListener(repositoryListener); + } + + @Nullable + @Override + protected ITreeChangeVisitor getTreeChangeVisitor(final ITree oldTree, final ITree newTree) { + assertSyncThread(); + return new ITreeChangeVisitor() { + @Override + public void containmentChanged(long nodeId) { + } + + @Override + public void childrenChanged(long parentId, @Nullable String role) { + assertSyncThread(); + if (parentId == projectNodeId && Objects.equals(role, LINKS.modules$Bi3g.getName())) { + enqueueSync(SyncDirection.TO_MPS, false, null); + } + } + + @Override + public void referenceChanged(long nodeId, @Nullable String role) { + } + + @Override + public void propertyChanged(long nodeId, @Nullable String role) { + } + }; + } + + @Override + public void doSyncToMPS(@NotNull ITree tree) { + Map mappings = new ProjectModulesSynchronizer(projectNodeId, mpsProject).syncToMPS(tree); + updateBindings(mappings, SyncDirection.TO_MPS); + } + + @Override + public void doSyncToCloud(IWriteTransaction t) { + Map mappings = new ProjectModulesSynchronizer(projectNodeId, mpsProject).syncToCloud(t); + updateBindings(mappings, SyncDirection.TO_CLOUD); + } + + private void updateBindings(final Map mappings, final SyncDirection syncDirection) { + Iterable> mappingsWithoutReadonly = MapSequence.fromMap(mappings).where(new IWhereFilter>() { + public boolean accept(IMapping it) { + return !(it.value().isPackaged()) && !(it.value().isReadOnly()); + } + }); + + final Map bindings = MapSequence.fromMap(new HashMap()); + Sequence.fromIterable(getOwnedBindings()).ofType(ProjectModuleBinding.class).visitAll(new IVisitor() { + public void visit(ProjectModuleBinding it) { + MapSequence.fromMap(bindings).put(it.getModuleNodeId(), it); + } + }); + + List toAdd = Sequence.fromIterable(mappingsWithoutReadonly).select(new ISelector, Long>() { + public Long select(IMapping it) { + return it.key(); + } + }).subtract(SetSequence.fromSet(MapSequence.fromMap(bindings).keySet())).toListSequence(); + List toRemove = SetSequence.fromSet(MapSequence.fromMap(bindings).keySet()).subtract(Sequence.fromIterable(mappingsWithoutReadonly).select(new ISelector, Long>() { + public Long select(IMapping it) { + return it.key(); + } + })).toListSequence(); + + ListSequence.fromList(toRemove).visitAll(new IVisitor() { + public void visit(Long it) { + ProjectModuleBinding binding = MapSequence.fromMap(bindings).get(it); + binding.deactivate(null); + binding.setOwner(null); + } + }); + + ListSequence.fromList(toAdd).visitAll(new IVisitor() { + public void visit(Long it) { + ProjectModuleBinding binding = new ProjectModuleBinding(it, MapSequence.fromMap(mappings).get(it), syncDirection); + binding.setOwner(ProjectBinding.this); + binding.activate(null); + } + }); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Project$An = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, "org.modelix.model.repositoryconcepts.structure.Project"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink modules$Bi3g = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, 0x37a0917d689de9e2L, "modules"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectModuleBinding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectModuleBinding.java new file mode 100644 index 00000000..29ba109d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectModuleBinding.java @@ -0,0 +1,20 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.module.SModule; + +public class ProjectModuleBinding extends ModuleBinding { + + private SModule module; + + public ProjectModuleBinding(long moduleNodeId, SModule module, SyncDirection initialSyncDirection) { + super(moduleNodeId, initialSyncDirection); + this.module = module; + } + + @Override + public SModule getModule() { + return module; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectModulesSynchronizer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectModulesSynchronizer.java new file mode 100644 index 00000000..4edf5625 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/ProjectModulesSynchronizer.java @@ -0,0 +1,148 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.project.MPSProject; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import jetbrains.mps.project.Solution; +import org.modelix.model.api.ITree; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.modelix.model.api.IConcept; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.jetbrains.mps.openapi.module.SModuleId; +import jetbrains.mps.project.ModuleId; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import jetbrains.mps.module.ModuleDeleteHelper; +import java.util.Collections; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Objects; +import org.jetbrains.mps.openapi.persistence.PersistenceFacade; +import org.modelix.model.api.IWriteTransaction; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SConcept; +import org.jetbrains.mps.openapi.language.SProperty; + +public class ProjectModulesSynchronizer extends Synchronizer { + + private MPSProject project; + + public ProjectModulesSynchronizer(long cloudParentId, MPSProject project) { + super(cloudParentId, LINKS.modules$Bi3g.getName()); + this.project = project; + } + + public MPSProject getProject() { + return project; + } + + @Override + protected Iterable getMPSChildren() { + List projectModules = project.getProjectModules(); + return ListSequence.fromList(projectModules).where(new IWhereFilter() { + public boolean accept(SModule it) { + return it instanceof Solution; + } + }); + } + + @Override + protected Iterable getCloudChildren(final ITree tree) { + return Sequence.fromIterable(super.getCloudChildren(tree)).where(new IWhereFilter() { + public boolean accept(Long it) { + IConcept concept = tree.getConcept(it); + return concept.isExactly(SConceptAdapter.wrap(CONCEPTS.Module$4i)) || concept.isSubConceptOf(SConceptAdapter.wrap(CONCEPTS.Solution$q3)); + } + }); + } + + @Override + protected SModule createMPSChild(ITree tree, long cloudChildId) { + SModuleId id = getModuleId(tree, cloudChildId); + if (id == null) { + id = ModuleId.foreign("cloud-" + cloudChildId); + } + String name = tree.getProperty(cloudChildId, PROPS.name$MnvL.getName()); + IConcept concept = tree.getConcept(cloudChildId); + return createModule(name, id, cloudChildId, SConceptAdapter.unwrap(concept)); + } + + protected SModule createModule(String name, SModuleId id, long modelNodeId, SAbstractConcept type) { + if (type.isSubConceptOf(CONCEPTS.Language$qy)) { + return null; + } else if (type.isSubConceptOf(CONCEPTS.DevKit$r1)) { + return null; + } else { + return MPSProjectUtils.createModule(project, name, (ModuleId) id, this); + } + } + + @Override + public void removeMPSChild(SModule mpsChild) { + new ModuleDeleteHelper(project).deleteModules(Collections.singletonList(mpsChild), false, true); + project.removeModule(mpsChild); + } + + @Override + public Map associate(ITree tree, List cloudChildren, List mpsChildren, SyncDirection direction) { + Map result = MapSequence.fromMap(new HashMap()); + List availableModules = ListSequence.fromListWithValues(new ArrayList(), mpsChildren); + + for (long cloudModuleId : cloudChildren) { + SModuleId id = getModuleId(tree, cloudModuleId); + String name = tree.getProperty(cloudModuleId, PROPS.name$MnvL.getName()); + + // There can be modules with duplicate names. That's why we can't just search in a map. + Iterator itr = ListSequence.fromList(availableModules).iterator(); + while (itr.hasNext()) { + SModule it = itr.next(); + if (id != null && Objects.equals(it.getModuleId(), id) || Objects.equals(it.getModuleName(), name)) { + MapSequence.fromMap(result).put(cloudModuleId, it); + itr.remove(); + break; + } + } + } + + return result; + } + + protected SModuleId getModuleId(ITree tree, long cloudModuleId) { + String serializedId = tree.getProperty(cloudModuleId, PROPS.id$7MjP.getName()); + if ((serializedId == null || serializedId.length() == 0)) { + return null; + } + return PersistenceFacade.getInstance().createModuleId(serializedId); + } + + @Override + public long createCloudChild(IWriteTransaction t, SModule mpsChild) { + long modelNodeId = t.addNewChild(getCloudParentId(), LINKS.modules$Bi3g.getName(), -1, SConceptAdapter.wrap(CONCEPTS.Module$4i)); + t.setProperty(modelNodeId, PROPS.id$7MjP.getName(), mpsChild.getModuleId().toString()); + t.setProperty(modelNodeId, PROPS.name$MnvL.getName(), mpsChild.getModuleName()); + return modelNodeId; + } + + private static final class LINKS { + /*package*/ static final SContainmentLink modules$Bi3g = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, 0x37a0917d689de9e2L, "modules"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + /*package*/ static final SConcept Solution$q3 = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x65e0d25ff052e203L, "org.modelix.model.repositoryconcepts.structure.Solution"); + /*package*/ static final SConcept DevKit$r1 = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x65e0d25ff052e205L, "org.modelix.model.repositoryconcepts.structure.DevKit"); + /*package*/ static final SConcept Language$qy = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x65e0d25ff052e204L, "org.modelix.model.repositoryconcepts.structure.Language"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$7MjP = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x3aa34013f2a802e0L, "id"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/RootBinding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/RootBinding.java new file mode 100644 index 00000000..76d84c03 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/RootBinding.java @@ -0,0 +1,108 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.IBranchListener; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.api.IBranch; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.api.ITree; +import java.util.Objects; +import java.util.List; +import org.modelix.model.api.ITreeChangeVisitor; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.modelix.model.api.IWriteTransaction; +import org.jetbrains.annotations.Nullable; + +/** + * Just a parent for all actual bindings + */ +public class RootBinding extends Binding implements IBranchListener { + + private final ICloudRepository cloudRepository; + private final SyncQueue syncQueue = new SyncQueue(this); + private boolean disposed = false; + + public RootBinding(ICloudRepository cloudRepository) { + super(null); + this.cloudRepository = cloudRepository; + activate(null); + } + + public RootBinding(ModelServerConnection connection, RepositoryId cloudRepositoryId) { + this(new CloudRepository(connection, cloudRepositoryId)); + } + + public SyncQueue getSyncQueue() { + return syncQueue; + } + + @Override + public String toString() { + return "bindings"; + } + + @Override + public IBranch getBranch() { + IBranch branch = super.getBranch(); + return (branch != null ? branch : cloudRepository.getBranch()); + } + + @Override + @NotNull + public ICloudRepository getCloudRepository() { + return cloudRepository; + } + + @Override + public void treeChanged(@NotNull final ITree oldTree, @NotNull final ITree newTree) { + if (syncQueue.isSynchronizing()) { + return; + } + enqueueSync(SyncDirection.TO_MPS, false, null); + } + + @Override + protected void doSyncToMPS(@NotNull final ITree newTree) { + assertSyncThread(); + final ITree oldTree = syncQueue.getLastTreeAfterSync(); + if (oldTree != null && !(Objects.equals(newTree, oldTree))) { + List visitors = Sequence.fromIterable(getAllBindings()).select(new ISelector() { + public ITreeChangeVisitor select(Binding it) { + return it.getTreeChangeVisitor(oldTree, newTree); + } + }).where(new NotNullWhereFilter()).toListSequence(); + if (ListSequence.fromList(visitors).isNotEmpty()) { + newTree.visitChanges(oldTree, new TreeChangeMulticaster(visitors)); + } + } + } + + @Override + public void doSyncToCloud(IWriteTransaction t) { + } + + @Nullable + @Override + protected ITreeChangeVisitor getTreeChangeVisitor(final ITree oldTree, final ITree newTree) { + return null; + } + + @Override + protected void doActivate() { + if (disposed) { + throw new IllegalStateException("Reactivation not supported"); + } + cloudRepository.getActiveBranch().addListener(this); + } + + @Override + protected void doDeactivate() { + disposed = true; + cloudRepository.getActiveBranch().removeListener(this); + syncQueue.dispose(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SModelUtils.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SModelUtils.java new file mode 100644 index 00000000..c60303da --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SModelUtils.java @@ -0,0 +1,42 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import java.util.List; +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.mps.openapi.model.SModel; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.LinkedList; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.jetbrains.mps.openapi.module.SModuleReference; +import jetbrains.mps.extapi.model.SModelDescriptorStub; +import org.jetbrains.mps.openapi.language.SLanguage; + +public class SModelUtils { + public SModelUtils() { + } + public static List getRootsAsList(final SModel _this) { + List nodes = ListSequence.fromList(new LinkedList()); + for (SNode node : Sequence.fromIterable(_this.getRootNodes())) { + ListSequence.fromList(nodes).addElement(node); + } + return nodes; + } + public static void addDevKit(final SModel _this, SModuleReference devKitModuleReference) { + if (_this instanceof SModelDescriptorStub) { + SModelDescriptorStub dsmd = ((SModelDescriptorStub) _this); + dsmd.addDevKit(devKitModuleReference); + } else { + throw new IllegalStateException("Unable to handle this model " + _this + " (class: " + _this.getClass().getCanonicalName() + ")"); + } + } + public static void addLanguageImport(final SModel _this, SLanguage sLanguage, int version) { + if (_this instanceof SModelDescriptorStub) { + SModelDescriptorStub dsmd = ((SModelDescriptorStub) _this); + dsmd.addLanguage(sLanguage); + dsmd.setLanguageImportVersion(sLanguage, version); + } else { + throw new IllegalStateException("Unable to handle this model " + _this + " (class: " + _this.getClass().getCanonicalName() + ")"); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SModuleUtils.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SModuleUtils.java new file mode 100644 index 00000000..e5ab8955 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SModuleUtils.java @@ -0,0 +1,49 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.model.SModelId; +import org.jetbrains.mps.openapi.persistence.ModelRoot; +import org.jetbrains.mps.openapi.model.SModelName; +import jetbrains.mps.persistence.DefaultModelRoot; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import jetbrains.mps.persistence.ModelCannotBeCreatedException; +import org.apache.log4j.Level; +import java.util.List; +import jetbrains.mps.smodel.SModelStereotype; + +public class SModuleUtils { + private static final Logger LOG = LogManager.getLogger(SModuleUtils.class); + public SModuleUtils() { + } + public static SModel createModel(final SModule _this, String name, SModelId id) { + Iterable modelRoots = _this.getModelRoots(); + final SModelName modelName = new SModelName(name); + DefaultModelRoot modelRoot = Sequence.fromIterable(modelRoots).ofType(DefaultModelRoot.class).findFirst(new IWhereFilter() { + public boolean accept(DefaultModelRoot it) { + return it.canCreateModel(modelName); + } + }); + try { + return modelRoot.createModel(modelName, null, null, new ModelPersistenceWithFixedId(_this.getModuleReference(), id)); + } catch (ModelCannotBeCreatedException e) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to create model " + modelName, e); + } + } + return null; + } + public static List getModelsWithoutDescriptor(final SModule _this) { + Iterable models = _this.getModels(); + return Sequence.fromIterable(models).where(new IWhereFilter() { + public boolean accept(SModel it) { + return !(SModelStereotype.isDescriptorModel(it)); + } + }).toListSequence(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SharedExecutors.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SharedExecutors.java new file mode 100644 index 00000000..0e89a3b3 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SharedExecutors.java @@ -0,0 +1,37 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import org.apache.log4j.Level; +import java.util.concurrent.TimeUnit; + +public class SharedExecutors { + private static final Logger LOG = LogManager.getLogger(SharedExecutors.class); + public static final ExecutorService FIXED = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1); + public static final ScheduledExecutorService SCHEDULED = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors() + 1); + + public static void shutdownAll() { + SCHEDULED.shutdown(); + FIXED.shutdown(); + } + + public static ScheduledFuture fixDelay(int milliSeconds, final Runnable r) { + return SCHEDULED.scheduleWithFixedDelay(new Runnable() { + public void run() { + try { + r.run(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + }, milliSeconds, milliSeconds, TimeUnit.MILLISECONDS); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncDirection.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncDirection.java new file mode 100644 index 00000000..f430e740 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncDirection.java @@ -0,0 +1,9 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + + +public enum SyncDirection { + TO_MPS(), + TO_CLOUD() +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncQueue.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncQueue.java new file mode 100644 index 00000000..26606a62 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncQueue.java @@ -0,0 +1,308 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.LinkedHashMap; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.modelix.model.api.ITree; +import org.jetbrains.annotations.Nullable; +import java.util.Set; +import java.util.function.Function; +import jetbrains.mps.internal.collections.runtime.LinkedListSequence; +import java.util.LinkedList; +import java.util.function.Consumer; +import java.util.Collections; +import java.util.Comparator; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import jetbrains.mps.internal.collections.runtime.IMapping; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import java.util.Objects; +import java.util.HashSet; +import org.apache.log4j.Level; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.modelix.model.api.IBranch; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.modelix.model.api.IWriteTransaction; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +public class SyncQueue { + private static final Logger LOG = LogManager.getLogger(SyncQueue.class); + private RootBinding owner; + private final Map syncQueue = MapSequence.fromMap(new LinkedHashMap(16, (float) 0.75, false)); + private volatile boolean isSynchronizing = false; + private final Object syncLock = new Object(); + private final List activeLocks = ListSequence.fromList(new ArrayList()); + private final FlushExecutor flushExecutor = new FlushExecutor(); + private Thread syncThread = null; + private ITree lastTreeAfterSync = null; + + public SyncQueue(RootBinding owner) { + this.owner = owner; + } + + @Nullable + public SyncTask getTask(Binding binding) { + return MapSequence.fromMap(syncQueue).get(binding); + } + + public ITree getLastTreeAfterSync() { + return this.lastTreeAfterSync; + } + + public void assertSyncThread() { + if (Thread.currentThread() != syncThread) { + throw new RuntimeException("Call only allowed from sync thread (" + syncThread + "), but current thread is " + Thread.currentThread()); + } + } + + public void dispose() { + } + + public boolean enqueue(SyncTask task) { + if (task.binding.getRootBinding() != owner) { + throw new IllegalArgumentException(task.binding + " is not attached to " + this); + } + synchronized (syncQueue) { + SyncTask existingTask = MapSequence.fromMap(syncQueue).get(task.binding); + if (existingTask != null) { + if (existingTask.direction == task.direction && existingTask.isInitialSync == task.isInitialSync) { + return false; + } + throw new RuntimeException("Cannot add " + task + ". Queue has pending " + existingTask); + } + MapSequence.fromMap(syncQueue).put(task.binding, task); + } + flushExecutor.submitFlush(); + return true; + } + + + public void flush() { + flushExecutor.flush(); + } + + public boolean isSynchronizing() { + return isSynchronizing; + } + + private void loadFromQueue(Map, List> locks2tasks) { + List queueElements; + synchronized (syncQueue) { + queueElements = ListSequence.fromListWithValues(new ArrayList(), MapSequence.fromMap(syncQueue).values()); + MapSequence.fromMap(syncQueue).clear(); + } + for (SyncTask task : ListSequence.fromList(queueElements)) { + ListSequence.fromList(locks2tasks.computeIfAbsent(task.requiredLocks, new Function, List>() { + public List apply(Set k) { + return LinkedListSequence.fromLinkedListNew(new LinkedList()); + } + })).addElement(task); + } + locks2tasks.values().forEach(new Consumer>() { + public void accept(List it) { + Collections.sort(it, new Comparator() { + @Override + public int compare(SyncTask t1, SyncTask t2) { + return t1.binding.getDepth() - t2.binding.getDepth(); + } + }); + } + }); + } + + private void doFlush() { + final List processedTasks = ListSequence.fromList(new ArrayList()); + synchronized (syncLock) { + assert !(isSynchronizing); + try { + isSynchronizing = true; + syncThread = Thread.currentThread(); + final Map, List> locks2task = new LinkedHashMap, List>(); + loadFromQueue(locks2task); + while (Sequence.fromIterable(MapSequence.fromMap(locks2task).values()).translate(new ITranslator2, SyncTask>() { + public Iterable translate(List it) { + return it; + } + }).isNotEmpty()) { + for (final IMapping, List> entry : MapSequence.fromMap(locks2task).where(new IWhereFilter, List>>() { + public boolean accept(IMapping, List> it) { + return ListSequence.fromList(it.value()).isNotEmpty(); + } + })) { + runWithLocks(SetSequence.fromSet(entry.key()).sort(new ISelector() { + public Integer select(ELockType it) { + return it.ordinal(); + } + }, true).toListSequence(), new _FunctionTypes._void_P0_E0() { + public void invoke() { + List tasks = entry.value(); + while (ListSequence.fromList(tasks).isNotEmpty()) { + while (ListSequence.fromList(tasks).isNotEmpty()) { + SyncTask task = ListSequence.fromList(tasks).removeElementAt(0); + if (!(Objects.equals(SetSequence.fromSetWithValues(new HashSet(), activeLocks), task.requiredLocks))) { + throw new IllegalStateException(task + " requires locks " + task.requiredLocks + ", but active locks are " + activeLocks); + } + ListSequence.fromList(processedTasks).addElement(task); + try { + task.run(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed: " + task, ex); + } + } + } + loadFromQueue(locks2task); + } + } + }); + } + } + } finally { + isSynchronizing = false; + syncThread = null; + } + } + for (SyncTask task : ListSequence.fromList(processedTasks)) { + try { + task.invokeCallbacks(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Exception in binding callback", ex); + } + } + } + } + + private void runWithLocks(final Iterable locks, final _FunctionTypes._void_P0_E0 body) { + if (Sequence.fromIterable(locks).isEmpty()) { + body.invoke(); + } else { + runWithLock(Sequence.fromIterable(locks).first(), new Runnable() { + public void run() { + runWithLocks(Sequence.fromIterable(locks).skip(1), body); + } + }); + } + } + + private void runWithLock(ELockType type, final Runnable body) { + assertSyncThread(); + if (ListSequence.fromList(activeLocks).contains(type)) { + throw new IllegalStateException("Lock " + type + " is already active"); + } + try { + ListSequence.fromList(activeLocks).addElement(type); + switch (type) { + case MPS_COMMAND: + CommandHelper.runInUndoTransparentCommand(new Runnable() { + public void run() { + Thread previousSyncThread = syncThread; + try { + syncThread = Thread.currentThread(); + body.run(); + } finally { + syncThread = previousSyncThread; + } + } + }); + break; + case MPS_READ: + MPSModuleRepository.getInstance().getModelAccess().runReadAction(new Runnable() { + public void run() { + body.run(); + } + }); + break; + case CLOUD_WRITE: + final IBranch branch = owner.getBranch(); + new PArea(branch).executeWrite(new Function0() { + public Unit invoke() { + body.run(); + final IWriteTransaction t = branch.getWriteTransaction(); + Iterable detachedNodes = t.getChildren(ITree.ROOT_ID, ITree.DETACHED_NODES_ROLE); + Sequence.fromIterable(detachedNodes).toListSequence().visitAll(new IVisitor() { + public void visit(Long it) { + t.deleteNode(it); + } + }); + lastTreeAfterSync = t.getTree(); + return Unit.INSTANCE; + } + }); + break; + case CLOUD_READ: + new PArea(owner.getBranch()).executeRead(new Function0() { + public Unit invoke() { + body.run(); + lastTreeAfterSync = owner.getBranch().getTransaction().getTree(); + return Unit.INSTANCE; + } + }); + break; + default: + throw new RuntimeException("Unknown lock type: " + type); + } + } finally { + ListSequence.fromList(activeLocks).removeLastElement(); + } + } + + public class FlushExecutor { + private final Object asyncFlushLock = new Object(); + private Future currentAsyncFlush; + private final AtomicBoolean flushRequested = new AtomicBoolean(false); + + private synchronized Future submitFlush() { + synchronized (asyncFlushLock) { + flushRequested.set(true); + if (currentAsyncFlush != null) { + if (currentAsyncFlush.isCancelled() || currentAsyncFlush.isDone()) { + currentAsyncFlush = null; + } + } + if (currentAsyncFlush == null) { + currentAsyncFlush = SharedExecutors.FIXED.submit(new Runnable() { + public void run() { + while (flushRequested.getAndSet(false)) { + doFlush(); + } + } + }); + } + return currentAsyncFlush; + } + } + + public void flush() { + try { + check_kjxrbf_a0a0a6ib(submitFlush(), this); + } catch (InterruptedException e) { + } catch (TimeoutException e) { + } catch (ExecutionException e) { + } + } + } + private static Object check_kjxrbf_a0a0a6ib(Future checkedDotOperand, FlushExecutor checkedDotThisExpression) throws InterruptedException, ExecutionException, TimeoutException { + if (null != checkedDotOperand) { + return checkedDotOperand.get(3, TimeUnit.MINUTES); + } + return null; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncTask.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncTask.java new file mode 100644 index 00000000..ff358e6c --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/SyncTask.java @@ -0,0 +1,92 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import java.util.Set; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import java.util.Collections; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import org.apache.log4j.Level; + +public class SyncTask implements Runnable { + private static final Logger LOG = LogManager.getLogger(SyncTask.class); + public final Binding binding; + public final SyncDirection direction; + public final Set requiredLocks; + private final Runnable implementation; + private final List callbacks = ListSequence.fromList(new ArrayList()); + private State state = State.NEW; + public final boolean isInitialSync; + + public SyncTask(Binding binding, SyncDirection direction, boolean initialSync, Set requiredLocks, Runnable implementation) { + this.binding = binding; + this.direction = direction; + this.isInitialSync = initialSync; + this.implementation = implementation; + this.requiredLocks = Collections.unmodifiableSet(SetSequence.fromSetWithValues(new HashSet(), requiredLocks)); + } + + @Override + public String toString() { + return "task[" + binding + ", " + direction + ", " + requiredLocks + "]"; + } + + @Override + public synchronized void run() { + if (state != State.NEW) { + throw new IllegalStateException("Current state: " + state); + } + try { + state = State.RUNNING; + if (binding.isActive()) { + binding.runningTask = this; + implementation.run(); + } else { + if (LOG.isEnabledFor(Level.WARN)) { + LOG.warn("Skipped " + this + ", because the binding is inactive"); + } + return; + } + } finally { + binding.runningTask = null; + state = State.DONE; + } + } + + public void invokeCallbacks() { + for (Runnable callback : ListSequence.fromList(callbacks)) { + try { + callback.run(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + } + + public boolean isDone() { + return state == State.DONE; + } + + public boolean isRunning() { + return state == State.RUNNING; + } + + public void whenDone(Runnable callback) { + if (callback != null) { + ListSequence.fromList(callbacks).addElement(callback); + } + } + + private enum State { + NEW(), + RUNNING(), + DONE() + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/Synchronizer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/Synchronizer.java new file mode 100644 index 00000000..e656bd8b --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/Synchronizer.java @@ -0,0 +1,92 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.ITree; +import org.modelix.model.api.IWriteTransaction; +import java.util.Map; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import jetbrains.mps.internal.collections.runtime.IVisitor; + +/** + * Synchronizes an unordered list of children + */ +public abstract class Synchronizer { + private long cloudParentId; + private String cloudRole; + + public Synchronizer(long cloudParentId, String cloudRole) { + this.cloudParentId = cloudParentId; + this.cloudRole = cloudRole; + } + + public long getCloudParentId() { + return this.cloudParentId; + } + + protected Iterable getCloudChildren(ITree tree) { + Iterable children = tree.getChildren(cloudParentId, cloudRole); + return children; + } + + protected abstract Iterable getMPSChildren(); + + protected abstract MPSChildT createMPSChild(ITree tree, long cloudChildId); + + public abstract long createCloudChild(IWriteTransaction t, MPSChildT mpsChild); + + public abstract void removeMPSChild(MPSChildT mpsChild); + + public abstract Map associate(ITree tree, List cloudChildren, List mpsChildren, SyncDirection direction); + + public Map syncToMPS(final ITree tree) { + List expectedChildren = Sequence.fromIterable(getCloudChildren(tree)).toListSequence(); + List existingChildren = Sequence.fromIterable(getMPSChildren()).toListSequence(); + + final Map mappings = associate(tree, expectedChildren, existingChildren, SyncDirection.TO_MPS); + + List toAdd = ListSequence.fromList(expectedChildren).subtract(SetSequence.fromSet(MapSequence.fromMap(mappings).keySet())).toListSequence(); + List toRemove = ListSequence.fromList(existingChildren).subtract(Sequence.fromIterable(MapSequence.fromMap(mappings).values())).toListSequence(); + + ListSequence.fromList(toRemove).visitAll(new IVisitor() { + public void visit(MPSChildT it) { + removeMPSChild(it); + } + }); + ListSequence.fromList(toAdd).visitAll(new IVisitor() { + public void visit(Long it) { + MapSequence.fromMap(mappings).put(it, createMPSChild(tree, it)); + } + }); + + return mappings; + } + + public Map syncToCloud(final IWriteTransaction t) { + List expectedChildren = Sequence.fromIterable(getMPSChildren()).toListSequence(); + List existingChildren = Sequence.fromIterable(getCloudChildren(t.getTree())).toListSequence(); + + final Map mappings = associate(t.getTree(), existingChildren, expectedChildren, SyncDirection.TO_CLOUD); + + List toAdd = ListSequence.fromList(expectedChildren).subtract(Sequence.fromIterable(MapSequence.fromMap(mappings).values())).toListSequence(); + List toRemove = ListSequence.fromList(existingChildren).subtract(SetSequence.fromSet(MapSequence.fromMap(mappings).keySet())).toListSequence(); + + ListSequence.fromList(toRemove).visitAll(new IVisitor() { + public void visit(Long it) { + t.moveChild(ITree.ROOT_ID, ITree.DETACHED_NODES_ROLE, -1, it); + } + }); + ListSequence.fromList(toAdd).visitAll(new IVisitor() { + public void visit(MPSChildT it) { + MapSequence.fromMap(mappings).put(createCloudChild(t, it), it); + } + }); + + return mappings; + } + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TestCloudRepository.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TestCloudRepository.java new file mode 100644 index 00000000..d956e386 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TestCloudRepository.java @@ -0,0 +1,32 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.IBranch; +import org.modelix.model.client.IIndirectBranch; +import org.modelix.model.lazy.RepositoryId; + +public class TestCloudRepository implements ICloudRepository { + private IBranch branch; + + public TestCloudRepository(IBranch branch) { + this.branch = branch; + } + + @Override + public String completeId() { + return "test"; + } + @Override + public IIndirectBranch getActiveBranch() { + return new NonIndirectBranch(branch); + } + @Override + public IBranch getBranch() { + return branch; + } + @Override + public RepositoryId getRepositoryId() { + return new RepositoryId("test"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransactionUtil.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransactionUtil.java new file mode 100644 index 00000000..2177577d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransactionUtil.java @@ -0,0 +1,99 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.area.IArea; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.mpsadapters.mps.NodeToSNodeAdapter; +import org.modelix.model.mpsadapters.mps.SNodeToNodeAdapter; +import org.modelix.model.api.INodeWrapper; +import org.modelix.model.mpsadapters.mps.ANode; +import jetbrains.mps.smodel.SNode; +import org.jetbrains.mps.openapi.module.SRepository; +import org.modelix.model.mpsadapters.mps.MPSArea; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.jetbrains.mps.openapi.model.SModel; + +public class TransactionUtil { + + public static IArea extractArea(Object obj) { + if (obj instanceof PNodeAdapter) { + return ((PNodeAdapter) obj).getArea(); + } else if (obj instanceof NodeToSNodeAdapter) { + return extractArea(SNodeToNodeAdapter.wrap(((NodeToSNodeAdapter) obj))); + } else if (obj instanceof SNodeToNodeAdapter) { + return extractArea(((SNodeToNodeAdapter) obj).getWrapped()); + } else if (obj instanceof IArea) { + return (IArea) obj; + } else if (obj instanceof INodeWrapper) { + return extractArea(((INodeWrapper) obj).getWrappedNode()); + } else if (obj instanceof ANode) { + return extractArea(ANode.unwrap(((ANode) obj))); + } else if (obj instanceof SNode) { + SRepository repository = check_276zg0_a0a0f0a1(((SNode) obj).getModel()); + return (repository == null ? new MPSArea() : new MPSArea(repository)); + } else { + return null; + } + } + + public static void runWriteOnNodes(Iterable nodesToRead, Runnable r) { + runWriteOnAreas(Sequence.fromIterable(nodesToRead).select(new ISelector() { + public IArea select(Object it) { + return extractArea(it); + } + }).where(new NotNullWhereFilter()), r); + } + + public static void runWriteOnNode(Object nodeToRead, Runnable r) { + runWriteOnNodes(Sequence.singleton(nodeToRead), r); + } + + public static void runWriteOnAreas(final Iterable areasToRead, final Runnable r) { + if (Sequence.fromIterable(areasToRead).isEmpty()) { + r.run(); + } else { + Sequence.fromIterable(areasToRead).first().executeWrite(new Function0() { + public Unit invoke() { + runReadOnAreas(Sequence.fromIterable(areasToRead).skip(1), r); + return Unit.INSTANCE; + } + }); + } + } + + public static void runReadOnNode(Object nodesToRead, Runnable r) { + runReadOnNodes(Sequence.singleton(nodesToRead), r); + } + + public static void runReadOnNodes(Iterable nodesToRead, Runnable r) { + runReadOnAreas(Sequence.fromIterable(nodesToRead).select(new ISelector() { + public IArea select(Object it) { + return extractArea(it); + } + }).where(new NotNullWhereFilter()), r); + } + + public static void runReadOnAreas(final Iterable areasToRead, final Runnable r) { + if (Sequence.fromIterable(areasToRead).isEmpty()) { + r.run(); + } else { + Sequence.fromIterable(areasToRead).first().executeRead(new Function0() { + public Unit invoke() { + runReadOnAreas(Sequence.fromIterable(areasToRead).skip(1), r); + return Unit.INSTANCE; + } + }); + } + } + private static SRepository check_276zg0_a0a0f0a1(SModel checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getRepository(); + } + return null; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransientModelsSynchronizer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransientModelsSynchronizer.java new file mode 100644 index 00000000..e034b144 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransientModelsSynchronizer.java @@ -0,0 +1,26 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.model.SModelId; + +public class TransientModelsSynchronizer extends ModelsSynchronizer { + + + public TransientModelsSynchronizer(long cloudParentId, CloudTransientModule module) { + super(cloudParentId, module); + } + + @Override + public CloudTransientModule getModule() { + return (CloudTransientModule) super.getModule(); + } + + @Override + protected SModel createModel(String name, SModelId id, long modelNodeId) { + CloudTransientModel model = new CloudTransientModel(getModule(), name, id, modelNodeId); + getModule().registerModel(model); + return model; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransientModuleBinding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransientModuleBinding.java new file mode 100644 index 00000000..b20f8c50 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TransientModuleBinding.java @@ -0,0 +1,87 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import java.util.concurrent.atomic.AtomicInteger; +import org.modelix.model.api.IBranch; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import org.modelix.model.api.PNodeAdapter; +import jetbrains.mps.project.ModuleId; +import jetbrains.mps.smodel.MPSModuleRepository; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class TransientModuleBinding extends ModuleBinding { + private static final AtomicInteger NAME_SEQUENCE = new AtomicInteger(0); + + private CloudTransientModule module; + + public TransientModuleBinding(long moduleNodeId) { + super(moduleNodeId, SyncDirection.TO_MPS); + } + + @Override + public CloudTransientModule getModule() { + return module; + } + + @Override + protected void doActivate() { + final IBranch branch = getBranch(); + String moduleName = new PArea(branch).executeRead(new Function0() { + public String invoke() { + return new PNodeAdapter(moduleNodeId, branch).getPropertyValue(PROPS.name$MnvL.getName()); + } + }); + String moduleIdStr = new PArea(branch).executeRead(new Function0() { + public String invoke() { + return new PNodeAdapter(moduleNodeId, branch).getPropertyValue(PROPS.id$7MjP.getName()); + } + }); + if ((moduleName == null || moduleName.length() == 0)) { + moduleName = "cloud.module" + NAME_SEQUENCE.incrementAndGet(); + } + ModuleId moduleId = ModuleId.foreign(getCloudRepository().completeId() + "-" + Long.toHexString(moduleNodeId)); + + if (moduleIdStr != null) { + ModuleId temptativeModuleId = ModuleId.fromString(moduleIdStr); + // This could happen because someone clone a module to Modelix and then try to bind it. + // In this case we want to give a warning to the user + if (CloudTransientModules.getInstance().isModuleIdUsed(temptativeModuleId)) { + ModelixNotifications.notifyWarning("Module ID already used", "We cannot load the module with the ID " + temptativeModuleId + " as the module id seems to be already used. We will load it with module id " + moduleId + " instead"); + } else { + moduleId = temptativeModuleId; + } + } + module = CloudTransientModules.getInstance().createModule(moduleName, moduleId); + super.doActivate(); + } + + @Override + protected void doDeactivate() { + super.doDeactivate(); + SharedExecutors.FIXED.execute(new Runnable() { + public void run() { + synchronized (TransientModuleBinding.this) { + MPSModuleRepository.getInstance().getModelAccess().runWriteAction(new Runnable() { + public void run() { + CloudTransientModules.getInstance().disposeModule(getModule()); + } + }); + } + } + }); + } + + @Override + protected Synchronizer getModelsSynchronizer() { + return new TransientModelsSynchronizer(getModuleNodeId(), getModule()); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + /*package*/ static final SProperty id$7MjP = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x3aa34013f2a802e0L, "id"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TreeChangeMulticaster.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TreeChangeMulticaster.java new file mode 100644 index 00000000..87b41f5d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TreeChangeMulticaster.java @@ -0,0 +1,61 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.ITreeChangeVisitorEx; +import java.util.List; +import org.modelix.model.api.ITreeChangeVisitor; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; + +/** + * ITree.visitChanges can be expensive. The performance is better if all listeners iterate over the changes together. + */ +public class TreeChangeMulticaster implements ITreeChangeVisitorEx { + private List visitors = ListSequence.fromList(new ArrayList()); + + public TreeChangeMulticaster(Iterable visitors) { + this.visitors = Sequence.fromIterable(visitors).toListSequence(); + } + + @Override + public void childrenChanged(long parent, @Nullable String role) { + for (ITreeChangeVisitor visitor : ListSequence.fromList(visitors)) { + visitor.childrenChanged(parent, role); + } + } + + @Override + public void containmentChanged(long node) { + for (ITreeChangeVisitor visitor : ListSequence.fromList(visitors)) { + visitor.containmentChanged(node); + } + } + @Override + public void propertyChanged(long node, @NotNull String role) { + for (ITreeChangeVisitor visitor : ListSequence.fromList(visitors)) { + visitor.propertyChanged(node, role); + } + } + @Override + public void referenceChanged(long node, @NotNull String role) { + for (ITreeChangeVisitor visitor : ListSequence.fromList(visitors)) { + visitor.referenceChanged(node, role); + } + } + @Override + public void nodeAdded(long node) { + for (ITreeChangeVisitorEx visitor : ListSequence.fromList(visitors).ofType(ITreeChangeVisitorEx.class)) { + visitor.nodeAdded(node); + } + } + @Override + public void nodeRemoved(long node) { + for (ITreeChangeVisitorEx visitor : ListSequence.fromList(visitors).ofType(ITreeChangeVisitorEx.class)) { + visitor.nodeRemoved(node); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TreeChangesCollector.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TreeChangesCollector.java new file mode 100644 index 00000000..7c199607 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/TreeChangesCollector.java @@ -0,0 +1,65 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.modelix.model.api.ITreeChangeVisitorEx; +import java.util.List; +import de.q60.mps.incremental.runtime.DependencyKey; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.modelix.model.api.IBranch; +import org.modelix.model.api.INodeReference; +import org.modelix.model.api.PNodeAdapter; +import de.q60.mps.shadowmodels.runtime.engine.ContainmentDependency; +import org.jetbrains.annotations.Nullable; +import de.q60.mps.shadowmodels.runtime.engine.RoleDependency; +import de.q60.mps.shadowmodels.runtime.engine.AllChildrenDependency; +import de.q60.mps.shadowmodels.runtime.model.persistent.SM_PNodeDependency; + +public class TreeChangesCollector implements ITreeChangeVisitorEx { + private final List changes = ListSequence.fromList(new ArrayList()); + private IBranch branch; + + public TreeChangesCollector(IBranch branch) { + this.branch = branch; + } + + public INodeReference toNodeRef(long nodeId) { + return new PNodeAdapter(nodeId, branch).getReference(); + } + + @Override + public void containmentChanged(long nodeId) { + ListSequence.fromList(changes).addElement(new ContainmentDependency(toNodeRef(nodeId))); + } + + @Override + public void childrenChanged(long nodeId, @Nullable String role) { + ListSequence.fromList(changes).addElement(new RoleDependency(toNodeRef(nodeId), role)); + ListSequence.fromList(changes).addElement(new AllChildrenDependency(toNodeRef(nodeId))); + } + + @Override + public void referenceChanged(long nodeId, String role) { + ListSequence.fromList(changes).addElement(new RoleDependency(toNodeRef(nodeId), role)); + } + + @Override + public void propertyChanged(long nodeId, String role) { + ListSequence.fromList(changes).addElement(new RoleDependency(toNodeRef(nodeId), role)); + } + + @Override + public void nodeRemoved(long nodeId) { + ListSequence.fromList(changes).addElement(new SM_PNodeDependency(branch, nodeId)); + } + + @Override + public void nodeAdded(long nodeId) { + ListSequence.fromList(changes).addElement(new SM_PNodeDependency(branch, nodeId)); + } + + public Iterable getChanges() { + return this.changes; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/UserObjectKey.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/UserObjectKey.java new file mode 100644 index 00000000..836c2633 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/UserObjectKey.java @@ -0,0 +1,36 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + + +public class UserObjectKey { + private final String id; + + public UserObjectKey(String id1) { + id = id1; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || this.getClass() != o.getClass()) { + return false; + } + + UserObjectKey that = (UserObjectKey) o; + if ((id != null ? !(((Object) id).equals(that.id)) : that.id != null)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = 0; + result = 31 * result + ((id != null ? id.hashCode() : 0)); + return result; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/WriteAccessUtil.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/WriteAccessUtil.java new file mode 100644 index 00000000..50f61ac8 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/WriteAccessUtil.java @@ -0,0 +1,26 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import org.jetbrains.mps.openapi.module.SRepository; +import org.jetbrains.mps.openapi.module.ModelAccess; +import com.intellij.openapi.application.ApplicationManager; + +public class WriteAccessUtil { + public static void runWrite(SRepository repo, final Runnable body) { + final ModelAccess modelAccess = repo.getModelAccess(); + if (modelAccess.canWrite()) { + body.run(); + } else { + if (modelAccess.canRead()) { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + public void run() { + modelAccess.runWriteAction(body); + } + }); + } else { + modelAccess.runWriteAction(body); + } + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/_Adapters.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/_Adapters.java new file mode 100644 index 00000000..b2974309 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/_Adapters.java @@ -0,0 +1,17 @@ +package org.modelix.model.mpsplugin; + +/*Generated by MPS */ + +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; + +public class _Adapters { + public static class _return_P0_E0_to_Runnable_adapter implements Runnable { + private _FunctionTypes._return_P0_E0 adapted; + public _return_P0_E0_to_Runnable_adapter(_FunctionTypes._return_P0_E0 adapted) { + this.adapted = adapted; + } + public void run() { + this.adapted.invoke(); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudBindingTreeNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudBindingTreeNode.java new file mode 100644 index 00000000..0b339f64 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudBindingTreeNode.java @@ -0,0 +1,106 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import jetbrains.mps.ide.ui.tree.TextTreeNode; +import org.modelix.model.mpsplugin.Binding; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.mpsplugin.ModelServerConnection; +import javax.swing.SwingUtilities; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import jetbrains.mps.internal.collections.runtime.ISelector; +import javax.swing.tree.TreeNode; + +public class CloudBindingTreeNode extends TextTreeNode { + private Binding binding; + private CloudRepository cloudRepository; + private Binding.IListener bindingListener = new Binding.IListener() { + @Override + public void bindingAdded(Binding binding) { + updateBindingsLater(); + } + + @Override + public void bindingRemoved(Binding binding) { + updateBindingsLater(); + } + + @Override + public void ownerChanged(Binding newOwner) { + updateBindingsLater(); + } + + @Override + public void bindingActivated() { + updateText(); + updateBindingsLater(); + } + + @Override + public void bindingDeactivated() { + updateText(); + updateBindingsLater(); + } + }; + + public CloudBindingTreeNode(Binding binding, CloudRepository repositoryInModelServer) { + super(binding.toString()); + this.binding = binding; + this.cloudRepository = repositoryInModelServer; + updateBindings(); + } + + public Binding getBinding() { + return binding; + } + + @Override + protected void onAdd() { + super.onAdd(); + binding.addListener(bindingListener); + } + + @Override + protected void onRemove() { + super.onRemove(); + binding.removeListener(bindingListener); + } + + public ModelServerConnection getModelServer() { + return cloudRepository.getModelServer(); + } + + public CloudRepository getRepositoryInModelServer() { + return cloudRepository; + } + + public void updateBindingsLater() { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + updateBindings(); + } + }); + } + + public void updateText() { + setText(binding.toString() + ((binding.isActive() ? "" : " [disabled]"))); + } + + public void updateBindings() { + final Map existing = MapSequence.fromMap(new HashMap()); + Sequence.fromIterable(TreeModelUtil.getChildren(this)).ofType(CloudBindingTreeNode.class).visitAll(new IVisitor() { + public void visit(CloudBindingTreeNode it) { + MapSequence.fromMap(existing).put(it.getBinding(), it); + } + }); + TreeModelUtil.setChildren(this, Sequence.fromIterable(binding.getOwnedBindings()).select(new ISelector() { + public CloudBindingTreeNode select(Binding it) { + return (MapSequence.fromMap(existing).containsKey(it) ? MapSequence.fromMap(existing).get(it) : new CloudBindingTreeNode(it, cloudRepository)); + } + }).ofType(TreeNode.class)); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudBranchTreeNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudBranchTreeNode.java new file mode 100644 index 00000000..37c9e9d8 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudBranchTreeNode.java @@ -0,0 +1,56 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import jetbrains.mps.ide.ui.tree.TextTreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.mpsplugin.CloudIcons; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.api.IBranch; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class CloudBranchTreeNode extends TextTreeNode { + + private ModelServerConnection modelServer; + private SNode branchInfo; + + public CloudBranchTreeNode(ModelServerConnection modelServer, SNode branchInfo) { + super(CloudIcons.BRANCH_ICON, SPropertyOperations.getString(branchInfo, PROPS.name$MnvL)); + this.modelServer = modelServer; + this.branchInfo = branchInfo; + setAllowsChildren(true); + } + + public SNode getBranchInfo() { + return this.branchInfo; + } + + public void updateChildren() { + } + + @Override + public void doubleClick() { + switchBranch(); + } + + public void switchBranch() { + RepositoryTreeNode treeTreeNode = this.getAncestor(RepositoryTreeNode.class); + RepositoryId repositoryId = treeTreeNode.getRepositoryId(); + final IBranch infoBranch = modelServer.getInfoBranch(); + String branchName = new PArea(infoBranch).executeRead(new Function0() { + public String invoke() { + return SPropertyOperations.getString(getBranchInfo(), PROPS.name$MnvL); + } + }); + modelServer.getActiveBranch(repositoryId).switchBranch(branchName); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNode.java new file mode 100644 index 00000000..a778734f --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNode.java @@ -0,0 +1,249 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import jetbrains.mps.ide.ui.tree.TextTreeNode; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.model.api.IBranch; +import org.modelix.model.api.INode; +import org.modelix.model.api.IConcept; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.mpsplugin.ModelServerConnection; +import jetbrains.mps.ide.ThreadUtils; +import org.modelix.model.mpsplugin.SharedExecutors; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import org.modelix.model.api.ITree; +import com.intellij.icons.AllIcons; +import org.modelix.model.mpsplugin.MPSNodeMapping; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.mpsadapters.mps.NodeToSNodeAdapter; +import org.jetbrains.mps.openapi.module.SRepository; +import org.modelix.model.mpsplugin.CommandHelper; +import org.modelix.model.area.ContextArea; +import org.modelix.model.mpsadapters.mps.MPSArea; +import jetbrains.mps.lang.core.behavior.BaseConcept__BehaviorDescriptor; +import org.apache.log4j.Level; +import jetbrains.mps.ide.icons.GlobalIconManager; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.LinkedHashMap; +import jetbrains.mps.internal.collections.runtime.Sequence; +import javax.swing.tree.TreeNode; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.ListSequence; + +/** + * This represents a single node inside the CloudView + */ +public class CloudNodeTreeNode extends TextTreeNode { + private static final Logger LOG = LogManager.getLogger(CloudNodeTreeNode.class); + + private IBranch branch; + private INode node; + private IConcept concept; + private boolean initialized; + + public CloudNodeTreeNode(IBranch branch, final INode node) { + super(""); + this.branch = branch; + this.node = node; + new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + CloudNodeTreeNode.this.concept = node.getConcept(); + long nodeId = ((PNodeAdapter) node).getNodeId(); + setNodeIdentifier(Long.toString(nodeId)); + updateText(); + return Unit.INSTANCE; + } + }); + } + + @Override + public boolean isInitialized() { + return initialized; + } + + @Override + public void update() { + doUpdate(); + } + + @Override + public void doUpdate() { + TreeModelUtil.clearChildren(this); + initialized = false; + } + + @Override + public boolean isLeaf() { + if (!(initialized)) { + return false; + } + return super.isLeaf(); + } + + @Override + protected void doUpdatePresentation() { + super.doUpdatePresentation(); + updateText(); + } + + @Override + protected void doInit() { + super.doInit(); + initialized = true; + updateText(); + updateChildren(); + } + + public INode getNode() { + return this.node; + } + + public IConcept getConcept() { + return this.concept; + } + + public IBranch getBranch() { + return this.branch; + } + + public ModelServerConnection getModelServer() { + return check_s6g2x7_a0a62(getAncestor(RepositoryTreeNode.class), this); + } + + public void setTextAndRepaint(String text) { + TreeModelUtil.setTextAndRepaint(this, text); + } + + public void updateText() { + ThreadUtils.runInUIThreadAndWait(new Runnable() { + public void run() { + LoadingIcon.apply(CloudNodeTreeNode.this); + } + }); + SharedExecutors.FIXED.execute(new _Adapters._return_P0_E0_to_Runnable_adapter(new _FunctionTypes._return_P0_E0() { + public Unit invoke() { + return new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + final Wrappers._T newText = new Wrappers._T(""); + String mappedMPSNodeID = null; + final long nodeId = ((PNodeAdapter) node).getNodeId(); + if (nodeId == ITree.ROOT_ID) { + newText.value = "ROOT #1"; + setIcon(AllIcons.Nodes.Folder); + } else { + final IConcept concept = node.getConcept(); + + if (concept != null) { + mappedMPSNodeID = MPSNodeMapping.mappedMpsNodeID(node); + final SNode snode = NodeToSNodeAdapter.wrap(node); + final SRepository mpsRepo = CommandHelper.getSRepository(); + if (mpsRepo == null) { + throw new IllegalStateException("repository should not be null"); + } + mpsRepo.getModelAccess().runReadAction(new _Adapters._return_P0_E0_to_Runnable_adapter(new _FunctionTypes._return_P0_E0() { + public Unit invoke() { + return ContextArea.INSTANCE.withAdditionalContext(new MPSArea(mpsRepo), new Function0() { + public Unit invoke() { + try { + newText.value = BaseConcept__BehaviorDescriptor.getPresentation_idhEwIMiw.invoke(snode) + " [" + concept.getLongName() + "] #" + Long.toHexString(nodeId); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to update the text", ex); + } + newText.value = "!!!" + ex.getMessage(); + } + try { + setIcon(GlobalIconManager.getInstance().getIconFor(snode)); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Failed to update the icon", ex); + } + } + return Unit.INSTANCE; + } + }); + } + })); + } else { + newText.value = "#" + nodeId; + } + } + String role = node.getRoleInParent(); + if (role != null) { + newText.value = role + " : " + newText.value; + } + if (mappedMPSNodeID != null) { + newText.value = newText.value + " -> MPS(" + mappedMPSNodeID + ")"; + } + ThreadUtils.runInUIThreadNoWait(new Runnable() { + public void run() { + setTextAndRepaint(newText.value); + } + }); + return Unit.INSTANCE; + } + }); + } + })); + } + + protected void updateChildren() { + if (!(initialized)) { + throw new RuntimeException(); + } + + final Map existing = MapSequence.fromMap(new LinkedHashMap(16, (float) 0.75, false)); + ThreadUtils.runInUIThreadAndWait(new Runnable() { + public void run() { + if (Sequence.fromIterable(TreeModelUtil.getChildren(CloudNodeTreeNode.this)).isEmpty()) { + TreeModelUtil.setChildren(CloudNodeTreeNode.this, Sequence.singleton(LoadingIcon.apply(new TextTreeNode("loading ...")))); + } + Sequence.fromIterable(TreeModelUtil.getChildren(CloudNodeTreeNode.this)).ofType(CloudNodeTreeNode.class).visitAll(new IVisitor() { + public void visit(CloudNodeTreeNode it) { + MapSequence.fromMap(existing).put(it.node, it); + } + }); + } + }); + SharedExecutors.FIXED.execute(new _Adapters._return_P0_E0_to_Runnable_adapter(new _FunctionTypes._return_P0_E0() { + public Unit invoke() { + return new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + Iterable allChildren = node.getAllChildren(); + final List newChildren = Sequence.fromIterable(allChildren).select(new ISelector() { + public CloudNodeTreeNode select(INode it) { + return (MapSequence.fromMap(existing).containsKey(it) ? MapSequence.fromMap(existing).get(it) : new CloudNodeTreeNode(branch, it)); + } + }).toListSequence(); + ThreadUtils.runInUIThreadNoWait(new Runnable() { + public void run() { + TreeModelUtil.setChildren(CloudNodeTreeNode.this, ListSequence.fromList(newChildren).ofType(TreeNode.class)); + ListSequence.fromList(newChildren).visitAll(new IVisitor() { + public void visit(CloudNodeTreeNode it) { + it.update(); + } + }); + } + }); + return Unit.INSTANCE; + } + }); + } + })); + } + private static ModelServerConnection check_s6g2x7_a0a62(RepositoryTreeNode checkedDotOperand, CloudNodeTreeNode checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModelServer(); + } + return null; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNodeBinding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNodeBinding.java new file mode 100644 index 00000000..f58af62f --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNodeBinding.java @@ -0,0 +1,42 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.mpsplugin.TransientModuleBinding; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.mpsplugin.ModelServerConnection; + +public class CloudNodeTreeNodeBinding { + public CloudNodeTreeNodeBinding() { + } + public static boolean isBoundAsAModule(final CloudNodeTreeNode _this) { + long nodeId = ((PNodeAdapter) _this.getNode()).getNodeId(); + RepositoryId repositoryId = _this.getAncestor(RepositoryTreeNode.class).getRepositoryId(); + if (_this.getModelServer().hasModuleBinding(repositoryId, nodeId)) { + return true; + } + return false; + } + public static TransientModuleBinding getTransientModuleBinding(final CloudNodeTreeNode _this) { + long nodeId = ((PNodeAdapter) _this.getNode()).getNodeId(); + RepositoryId repositoryId = _this.getAncestor(RepositoryTreeNode.class).getRepositoryId(); + List bindings = ListSequence.fromList(_this.getModelServer().getModuleBinding(repositoryId, nodeId)).ofType(TransientModuleBinding.class).toListSequence(); + if (ListSequence.fromList(bindings).count() == 0) { + return null; + } else if (ListSequence.fromList(bindings).count() == 1) { + return ListSequence.fromList(bindings).getElement(0); + } else { + throw new IllegalStateException("Multiple transient bindings for the same module are not expected"); + } + } + public static CloudRepository getTreeInRepository(final CloudNodeTreeNode _this) { + ModelServerConnection modelServer = _this.getAncestor(ModelServerTreeNode.class).getModelServer(); + RepositoryId repositoryId = _this.getAncestor(RepositoryTreeNode.class).getRepositoryId(); + CloudRepository treeInRepository = new CloudRepository(modelServer, repositoryId); + return treeInRepository; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNodeClassification.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNodeClassification.java new file mode 100644 index 00000000..09139e25 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudNodeTreeNodeClassification.java @@ -0,0 +1,42 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import org.modelix.model.api.INode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.api.ITree; +import org.modelix.model.api.IConcept; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class CloudNodeTreeNodeClassification { + public CloudNodeTreeNodeClassification() { + } + public static boolean isCloudNodeRootNode(final CloudNodeTreeNode _this) { + INode node = _this.getNode(); + if (!(node instanceof PNodeAdapter)) { + return false; + } + return ((PNodeAdapter) node).getNodeId() == ITree.ROOT_ID; + } + public static boolean isCloudNodeModuleNode(final CloudNodeTreeNode _this) { + IConcept concept = _this.getConcept(); + if (concept == null) { + return false; + } + return concept.isSubConceptOf(SConceptAdapter.wrap(CONCEPTS.Module$4i)); + } + public static boolean isCloudNodeAProjectNode(final CloudNodeTreeNode _this) { + IConcept concept = _this.getConcept(); + if (concept == null) { + return false; + } + return concept.isSubConceptOf(SConceptAdapter.wrap(CONCEPTS.Project$An)); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + /*package*/ static final SConcept Project$An = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, "org.modelix.model.repositoryconcepts.structure.Project"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudRootTreeNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudRootTreeNode.java new file mode 100644 index 00000000..7b4dee38 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudRootTreeNode.java @@ -0,0 +1,61 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import jetbrains.mps.ide.ui.tree.TextTreeNode; +import org.modelix.model.mpsplugin.ModelServerConnections; +import org.modelix.model.mpsplugin.CloudIcons; +import org.modelix.model.mpsplugin.ModelServerConnection; +import jetbrains.mps.internal.collections.runtime.Sequence; + +public class CloudRootTreeNode extends TextTreeNode { + private boolean myInitialized = false; + private ModelServerConnections.IListener repositoriesListener = new ModelServerConnections.IListener() { + @Override + public void repositoriesChanged() { + update(); + init(); + } + }; + + public CloudRootTreeNode() { + super(CloudIcons.ROOT_ICON, "Cloud"); + setAllowsChildren(true); + init(); + } + + @Override + public boolean isInitialized() { + return myInitialized; + } + + @Override + protected void doInit() { + myInitialized = true; + populate(); + } + + @Override + protected void doUpdate() { + removeAllChildren(); + myInitialized = false; + } + + protected void populate() { + for (ModelServerConnection repo : Sequence.fromIterable(ModelServerConnections.getInstance().getModelServers())) { + add(new ModelServerTreeNode(repo)); + } + } + + @Override + protected void onAdd() { + super.onAdd(); + ModelServerConnections.getInstance().addListener(repositoriesListener); + } + + @Override + protected void onRemove() { + super.onRemove(); + ModelServerConnections.getInstance().removeListener(repositoriesListener); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudView.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudView.java new file mode 100644 index 00000000..c3302cd3 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/CloudView.java @@ -0,0 +1,88 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import javax.swing.JPanel; +import jetbrains.mps.ide.ui.tree.MPSTree; +import java.awt.BorderLayout; +import javax.swing.JScrollPane; +import javax.swing.BorderFactory; +import com.intellij.openapi.actionSystem.DataProvider; +import jetbrains.mps.ide.ui.tree.MPSTreeNode; +import jetbrains.mps.ide.ui.tree.TextTreeNode; +import com.intellij.openapi.actionSystem.ActionGroup; +import jetbrains.mps.workbench.action.ActionUtils; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.NonNls; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; + +public class CloudView extends JPanel { + + private MPSTree tree = new CloudViewTree(); + + public CloudView() { + super(new BorderLayout()); + + JScrollPane scrollPane = new JScrollPane(tree); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + add(scrollPane, BorderLayout.CENTER); + + tree.rebuildLater(); + } + + public static class CloudViewTree extends MPSTree implements DataProvider { + + @Override + public void runRebuildAction(Runnable rebuildAction, boolean saveExpansion) { + super.runRebuildAction(rebuildAction, saveExpansion); + } + @Override + protected MPSTreeNode rebuild() { + TextTreeNode root = new TextTreeNode("Loading ..."); + root.add(new CloudRootTreeNode()); + setRootVisible(false); + return root; + } + @Override + protected ActionGroup createPopupActionGroup(MPSTreeNode node) { + if (node instanceof CloudRootTreeNode) { + return ActionUtils.getGroup("org.modelix.model.mpsplugin.plugin.CloudRootGroup_ActionGroup"); + } + if (node instanceof ModelServerTreeNode) { + return ActionUtils.getGroup("org.modelix.model.mpsplugin.plugin.ModelServerGroup_ActionGroup"); + } + if (node instanceof CloudNodeTreeNode) { + return ActionUtils.getGroup("org.modelix.model.mpsplugin.plugin.CloudNodeGroup_ActionGroup"); + } + if (node instanceof RepositoryTreeNode) { + return ActionUtils.getGroup("org.modelix.model.mpsplugin.plugin.RepositoryGroup_ActionGroup"); + } + if (node instanceof CloudBranchTreeNode) { + return ActionUtils.getGroup("org.modelix.model.mpsplugin.plugin.CloudBranchGroup_ActionGroup"); + } + if (node instanceof CloudBindingTreeNode) { + return ActionUtils.getGroup("org.modelix.model.mpsplugin.plugin.CloudBindingGroup_ActionGroup"); + } + return null; + } + private T getSelectedTreeNode(Class nodeClass) { + TreePath selectionPath = getSelectionPath(); + if (selectionPath == null) { + return null; + } + Object selectedNode = selectionPath.getLastPathComponent(); + return (nodeClass.isInstance(selectedNode) ? nodeClass.cast(selectedNode) : null); + } + @Nullable + @Override + public Object getData(@NotNull @NonNls String dataId) { + if (MPSCommonDataKeys.TREE_NODE.is(dataId)) { + return getSelectedTreeNode(TreeNode.class); + } + return null; + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/HistoryView.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/HistoryView.java new file mode 100644 index 00000000..d88b11c1 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/HistoryView.java @@ -0,0 +1,191 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import javax.swing.JPanel; +import javax.swing.table.DefaultTableModel; +import javax.swing.JTable; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import org.modelix.model.lazy.CLVersion; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.lazy.RepositoryId; +import javax.swing.JButton; +import java.awt.BorderLayout; +import javax.swing.JScrollPane; +import javax.swing.BorderFactory; +import java.awt.FlowLayout; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import org.modelix.model.client.ActiveBranch; +import java.util.UUID; +import org.modelix.model.api.IBranch; +import kotlin.jvm.functions.Function1; +import org.modelix.model.api.IWriteTransaction; +import kotlin.Unit; +import org.modelix.model.operations.OTWriteTransactionKt; +import org.modelix.model.operations.RevertToOp; +import org.modelix.model.lazy.KVEntryReference; +import org.modelix.model.persistent.CPVersion; +import com.intellij.openapi.application.ApplicationManager; +import jetbrains.mps.ide.ThreadUtils; +import org.modelix.model.lazy.IDeserializingKeyValueStore; +import org.modelix.model.LinearHistory; +import jetbrains.mps.internal.collections.runtime.IterableUtils; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.modelix.model.operations.IOperation; +import jetbrains.mps.internal.collections.runtime.ISelector; +import java.util.Vector; + +public class HistoryView extends JPanel { + private DefaultTableModel tableModel; + private JTable table; + private _FunctionTypes._return_P0_E0 versionGetter; + private List versions = ListSequence.fromList(new ArrayList()); + private ModelServerConnection modelServer; + private RepositoryId repositoryId; + private String previousBranchName; + private JButton resetButton; + private JButton revertButton; + + public HistoryView() { + setLayout(new BorderLayout()); + + tableModel = new DefaultTableModel(); + tableModel.addColumn("ID"); + tableModel.addColumn("Author"); + tableModel.addColumn("Time"); + tableModel.addColumn("Operations"); + tableModel.addColumn("Hash"); + + table = new JTable(tableModel); + JScrollPane scrollPane = new JScrollPane(table); + scrollPane.setBorder(BorderFactory.createEmptyBorder()); + add(scrollPane, BorderLayout.CENTER); + + JPanel buttonPanel = new JPanel(new FlowLayout()); + JButton loadButton = new JButton("Load Selected Version"); + loadButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + loadSelectedVersion(); + } + }); + buttonPanel.add(loadButton); + + resetButton = new JButton("Reset to ..."); + resetButton.setEnabled(false); + resetButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + restoreBranch(); + } + }); + buttonPanel.add(resetButton); + + revertButton = new JButton("Revert to Selected Version"); + revertButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + revertToSelectedVersion(); + } + }); + buttonPanel.add(revertButton); + + add(buttonPanel, BorderLayout.SOUTH); + } + + public void loadSelectedVersion() { + int index = table.getSelectedRow(); + if (0 <= index && index < ListSequence.fromList(versions).count()) { + CLVersion version = ListSequence.fromList(versions).getElement(index); + ActiveBranch branch = modelServer.getActiveBranch(repositoryId); + String branchName = "history" + UUID.randomUUID(); + String branchKey = repositoryId.getBranchKey(branchName); + modelServer.getClient().put(branchKey, version.getHash()); + branch.switchBranch(branchName); + resetButton.setEnabled(true); + } + } + + public void revertToSelectedVersion() { + int index = table.getSelectedRow(); + if (0 <= index && index < ListSequence.fromList(versions).count()) { + ActiveBranch activeBranch = modelServer.getActiveBranch(repositoryId); + final CLVersion versionToRevertTo = ListSequence.fromList(versions).getElement(index); + final CLVersion latestKnownVersion = activeBranch.getVersion(); + IBranch branch = activeBranch.getBranch(); + branch.runWriteT(new Function1() { + public Unit invoke(IWriteTransaction t) { + OTWriteTransactionKt.applyOperation(t, new RevertToOp(new KVEntryReference(latestKnownVersion.getData()), new KVEntryReference(versionToRevertTo.getData()))); + return Unit.INSTANCE; + } + }); + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + refreshHistory(); + } + }); + } + } + + public void restoreBranch() { + modelServer.getActiveBranch(repositoryId).switchBranch(previousBranchName); + resetButton.setEnabled(false); + } + + public void refreshHistory() { + loadHistory(modelServer, repositoryId, versionGetter); + } + + public void loadHistory(ModelServerConnection modelServer, RepositoryId repositoryId, final _FunctionTypes._return_P0_E0 headVersion) { + this.versionGetter = headVersion; + this.modelServer = modelServer; + this.repositoryId = repositoryId; + this.previousBranchName = modelServer.getActiveBranch(repositoryId).getBranchName(); + resetButton.setText("Reset to " + previousBranchName); + ThreadUtils.runInUIThreadAndWait(new Runnable() { + public void run() { + while (tableModel.getRowCount() > 0) { + tableModel.removeRow(0); + } + ListSequence.fromList(versions).clear(); + } + }); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + public void run() { + CLVersion version = headVersion.invoke(); + while (version != null) { + createTableRow(version); + if (version.isMerge()) { + IDeserializingKeyValueStore store = version.getStore(); + for (CLVersion v : ListSequence.fromList(new LinearHistory(version.getBaseVersion().getHash()).load(new CLVersion(version.getData().getMergedVersion1().getValue(store), store), new CLVersion(version.getData().getMergedVersion2().getValue(store), store)))) { + createTableRow(v); + } + } + if (ListSequence.fromList(versions).count() >= 500) { + break; + } + version = version.getBaseVersion(); + } + } + }); + } + private void createTableRow(final CLVersion version) { + ThreadUtils.runInUIThreadAndWait(new Runnable() { + public void run() { + String opsDescription; + if (version.isMerge()) { + opsDescription = "merge " + version.getMergedVersion1().getId() + " + " + version.getMergedVersion2().getId() + " (base " + version.getBaseVersion() + ")"; + } else { + opsDescription = "(" + version.getNumberOfOperations() + ") " + ((version.operationsInlined() ? IterableUtils.join(Sequence.fromIterable(((Iterable) version.getOperations())).select(new ISelector() { + public String select(IOperation it) { + return it.toString(); + } + }), " # ") : "...")); + } + tableModel.addRow(new Vector(ListSequence.fromListAndArray(new ArrayList(), Long.toHexString(version.getId()), version.getAuthor(), version.getTime(), opsDescription, version.getHash()))); + ListSequence.fromList(versions).addElement(version); + } + }); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/LoadingIcon.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/LoadingIcon.java new file mode 100644 index 00000000..dbf9db00 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/LoadingIcon.java @@ -0,0 +1,106 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import javax.swing.Icon; +import java.util.Set; +import jetbrains.mps.ide.ui.tree.MPSTreeNode; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import javax.swing.Timer; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import jetbrains.mps.ide.ui.tree.MPSTree; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.geom.Arc2D; + +public class LoadingIcon implements Icon { + private static LoadingIcon INSTANCE = new LoadingIcon(); + + private Set activeNodes = SetSequence.fromSet(new HashSet()); + private double angle; + private Timer timer; + private int inactivity = 0; + + public static T apply(final T treeNode) { + treeNode.setIcon(INSTANCE); + INSTANCE.register(treeNode); + return treeNode; + } + + public void register(MPSTreeNode treeNode) { + SetSequence.fromSet(activeNodes).addElement(treeNode); + ensureTimerRunning(); + } + + private void ensureTimerRunning() { + if (timer == null || !(timer.isRunning())) { + timer = new Timer(1000 / 60, new ActionListener() { + public void actionPerformed(ActionEvent e) { + rotate(); + if (SetSequence.fromSet(activeNodes).isEmpty()) { + if (inactivity > 5000 / 60) { + SetSequence.fromSet(activeNodes).clear(); + timer.stop(); + timer = null; + } else { + inactivity++; + } + return; + } + + for (MPSTree c : SetSequence.fromSet(activeNodes).select(new ISelector() { + public MPSTree select(MPSTreeNode it) { + return it.getTree(); + } + }).where(new NotNullWhereFilter()).distinct()) { + c.repaint(); + } + } + }); + timer.start(); + } + } + + private void rotate() { + angle = (angle - 360.0 / 120.0) % 360.0; + } + + @Override + public void paintIcon(Component component, Graphics graphics, int x, int y) { + inactivity = 0; + ensureTimerRunning(); + + double w = getIconWidth(); + double h = getIconHeight(); + Graphics2D g = (Graphics2D) graphics.create(); + try { + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + + g.setStroke(new BasicStroke(3.0f)); + g.setColor(new Color(80, 80, 80)); + + g.draw(new Arc2D.Double(2.0 + x, 2.0 + y, w - 4.0, h - 4.0, angle, 250.0, Arc2D.OPEN)); + } finally { + g.dispose(); + } + } + @Override + public int getIconWidth() { + return 16; + } + @Override + public int getIconHeight() { + return 16; + } + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/ModelServerTreeNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/ModelServerTreeNode.java new file mode 100644 index 00000000..a559788e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/ModelServerTreeNode.java @@ -0,0 +1,184 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import jetbrains.mps.ide.ui.tree.TextTreeNode; +import org.modelix.model.api.IBranchListener; +import org.modelix.model.api.ITree; +import javax.swing.SwingUtilities; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.api.IBranch; +import org.modelix.model.mpsplugin.CloudIcons; +import java.util.Map; +import org.jetbrains.mps.openapi.model.SNode; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.LinkedHashMap; +import jetbrains.mps.ide.ThreadUtils; +import jetbrains.mps.internal.collections.runtime.Sequence; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.SharedExecutors; +import java.util.List; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import jetbrains.mps.internal.collections.runtime.IListSequence; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.modelix.model.mpsplugin.ModelixNotifications; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; +import jetbrains.mps.internal.collections.runtime.NotNullWhereFilter; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; + +public class ModelServerTreeNode extends TextTreeNode { + private IBranchListener branchListener = new IBranchListener() { + @Override + public void treeChanged(ITree oldTree, ITree newTree) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ((CloudView.CloudViewTree) getTree()).runRebuildAction(new Runnable() { + public void run() { + updateChildren(); + } + }, true); + } + }); + } + }; + private ModelServerConnection modelServer; + private IBranch infoBranch; + private ModelServerConnection.IListener repoListener = new ModelServerConnection.IListener() { + @Override + public void connectionStatusChanged(final boolean connected) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if (connected) { + infoBranch = modelServer.getInfoBranch(); + if (getTree() != null) { + infoBranch.addListener(branchListener); + } + } + updateText(); + updateChildren(); + } + }); + } + }; + + public ModelServerTreeNode(ModelServerConnection modelServer) { + super(CloudIcons.MODEL_SERVER_ICON, modelServer.getBaseUrl()); + this.modelServer = modelServer; + setAllowsChildren(true); + setNodeIdentifier("" + System.identityHashCode(modelServer)); + modelServer.addListener(repoListener); + updateText(); + updateChildren(); + } + + public ModelServerConnection getModelServer() { + return this.modelServer; + } + + public void updateText() { + String text = modelServer.getBaseUrl(); + if (modelServer.isConnected()) { + text += " (" + modelServer.getId() + ")"; + } else { + text += " (not connected)"; + } + String email = modelServer.getEmail(); + if ((email != null && email.length() > 0)) { + text += " " + email; + } + setTextAndRepaint(text); + } + + public void setTextAndRepaint(String text) { + TreeModelUtil.setTextAndRepaint(this, text); + } + + public void updateChildren() { + if (modelServer.isConnected()) { + final Map existing = MapSequence.fromMap(new LinkedHashMap(16, (float) 0.75, false)); + ThreadUtils.runInUIThreadAndWait(new Runnable() { + public void run() { + if (Sequence.fromIterable(TreeModelUtil.getChildren(ModelServerTreeNode.this)).isEmpty()) { + TreeModelUtil.setChildren(ModelServerTreeNode.this, Sequence.singleton(LoadingIcon.apply(new TextTreeNode("loading ...")))); + } + for (RepositoryTreeNode node : Sequence.fromIterable(TreeModelUtil.getChildren(ModelServerTreeNode.this)).ofType(RepositoryTreeNode.class)) { + MapSequence.fromMap(existing).put(node.getRepositoryInfo(), node); + } + } + }); + + SharedExecutors.FIXED.execute(new Runnable() { + public void run() { + final List newChildren = new PArea(modelServer.getInfoBranch()).executeRead(new Function0>() { + public IListSequence invoke() { + SNode info = modelServer.getInfo(); + if (info == null) { + return ListSequence.fromList(new ArrayList()); + } + return ListSequence.fromList(SLinkOperations.getChildren(info, LINKS.repositories$b56J)).select(new ISelector() { + public TreeNode select(SNode it) { + TreeNode tn = null; + try { + tn = (MapSequence.fromMap(existing).containsKey(it) ? MapSequence.fromMap(existing).get(it) : new RepositoryTreeNode(modelServer, it)); + } catch (Throwable t) { + t.printStackTrace(); + ModelixNotifications.notifyError("Repository in invalid state", "Repository " + SPropertyOperations.getString(it, PROPS.id$baYB) + " cannot be loaded: " + t.getMessage()); + } + return tn; + } + }).where(new NotNullWhereFilter()).toListSequence(); + } + }); + + ThreadUtils.runInUIThreadNoWait(new Runnable() { + public void run() { + TreeModelUtil.setChildren(ModelServerTreeNode.this, newChildren); + Sequence.fromIterable(TreeModelUtil.getChildren(ModelServerTreeNode.this)).ofType(RepositoryTreeNode.class).visitAll(new IVisitor() { + public void visit(RepositoryTreeNode it) { + it.updateChildren(); + } + }); + } + }); + } + }); + } else { + ThreadUtils.runInUIThreadNoWait(new Runnable() { + public void run() { + TreeModelUtil.clearChildren(ModelServerTreeNode.this); + } + }); + } + } + + @Override + protected void onAdd() { + super.onAdd(); + if (infoBranch != null) { + infoBranch.addListener(branchListener); + } + } + + @Override + protected void onRemove() { + super.onRemove(); + if (infoBranch != null) { + modelServer.getInfoBranch().removeListener(branchListener); + } + } + + private static final class LINKS { + /*package*/ static final SContainmentLink repositories$b56J = MetaAdapterFactory.getContainmentLink(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcbfL, 0x62b7d9b07cecbcc2L, "repositories"); + } + + private static final class PROPS { + /*package*/ static final SProperty id$baYB = MetaAdapterFactory.getProperty(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, 0x62b7d9b07cecbcc6L, "id"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/RepositoryTreeNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/RepositoryTreeNode.java new file mode 100644 index 00000000..772392c0 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/RepositoryTreeNode.java @@ -0,0 +1,160 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import jetbrains.mps.ide.ui.tree.TextTreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.client.ActiveBranch; +import org.modelix.model.api.IBranchListener; +import org.modelix.model.api.ITree; +import javax.swing.SwingUtilities; +import org.modelix.model.mpsplugin.CloudIcons; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; +import org.modelix.model.mpsplugin.CloudRepository; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import javax.swing.tree.TreeNode; +import java.util.Map; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.LinkedHashMap; +import jetbrains.mps.ide.ThreadUtils; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.modelix.model.mpsplugin.SharedExecutors; +import java.util.List; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import jetbrains.mps.internal.collections.runtime.IListSequence; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.modelix.model.api.IBranch; +import org.modelix.model.api.PNodeAdapter; +import java.util.Objects; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SContainmentLink; + +public class RepositoryTreeNode extends TextTreeNode { + + private ModelServerConnection modelServer; + private SNode repositoryInfo; + private RepositoryId repositoryId; + private ActiveBranch activeBranch; + private TextTreeNode dataTreeNode = new TextTreeNode("data"); + private TextTreeNode branchesTreeNode = new TextTreeNode("branches"); + private CloudBindingTreeNode bindingsTreeNode; + private IBranchListener branchListener = new IBranchListener() { + @Override + public void treeChanged(ITree oldTree, ITree newTree) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ((CloudView.CloudViewTree) getTree()).runRebuildAction(new Runnable() { + public void run() { + updateData(); + } + }, true); + } + }); + } + }; + + public RepositoryTreeNode(ModelServerConnection modelServer, SNode repositoryInfo) { + super(CloudIcons.REPOSITORY_ICON, SPropertyOperations.getString(repositoryInfo, PROPS.id$baYB)); + try { + this.modelServer = modelServer; + this.repositoryInfo = repositoryInfo; + this.repositoryId = new RepositoryId(SPropertyOperations.getString(repositoryInfo, PROPS.id$baYB)); + this.activeBranch = modelServer.getActiveBranch(new RepositoryId(SPropertyOperations.getString(repositoryInfo, PROPS.id$baYB))); + CloudRepository cloudRepository = new CloudRepository(modelServer, repositoryId); + bindingsTreeNode = new CloudBindingTreeNode(cloudRepository.getRootBinding(), cloudRepository); + setAllowsChildren(true); + TreeModelUtil.setChildren(this, ListSequence.fromListAndArray(new ArrayList(), dataTreeNode, branchesTreeNode, bindingsTreeNode)); + activeBranch.addListener(branchListener); + updateData(); + } catch (RuntimeException e) { + throw new RuntimeException("Unable to initialize RepositoryTreeNode for repository with id " + SPropertyOperations.getString(repositoryInfo, PROPS.id$baYB), e); + } + } + + @Override + protected void onRemove() { + super.onRemove(); + activeBranch.removeListener(branchListener); + } + + public SNode getRepositoryInfo() { + return repositoryInfo; + } + + public RepositoryId getRepositoryId() { + return repositoryId; + } + + public ModelServerConnection getModelServer() { + return this.modelServer; + } + + public void updateChildren() { + updateBranches(); + } + + public void updateBranches() { + final Map existing = MapSequence.fromMap(new LinkedHashMap(16, (float) 0.75, false)); + ThreadUtils.runInUIThreadAndWait(new Runnable() { + public void run() { + if (Sequence.fromIterable(TreeModelUtil.getChildren(RepositoryTreeNode.this)).isEmpty()) { + TreeModelUtil.setChildren(RepositoryTreeNode.this, Sequence.singleton(LoadingIcon.apply(new TextTreeNode("loading ...")))); + } + for (CloudBranchTreeNode node : Sequence.fromIterable(TreeModelUtil.getChildren(branchesTreeNode)).ofType(CloudBranchTreeNode.class)) { + MapSequence.fromMap(existing).put(node.getBranchInfo(), node); + } + } + }); + + SharedExecutors.FIXED.execute(new Runnable() { + public void run() { + final List newChildren = new PArea(modelServer.getInfoBranch()).executeRead(new Function0>() { + public IListSequence invoke() { + return ListSequence.fromList(SLinkOperations.getChildren(repositoryInfo, LINKS.branches$b5_g)).select(new ISelector() { + public TreeNode select(SNode it) { + TreeNode tn = (MapSequence.fromMap(existing).containsKey(it) ? MapSequence.fromMap(existing).get(it) : new CloudBranchTreeNode(modelServer, it)); + return tn; + } + }).toListSequence(); + } + }); + ThreadUtils.runInUIThreadNoWait(new Runnable() { + public void run() { + TreeModelUtil.setChildren(branchesTreeNode, newChildren); + } + }); + } + }); + } + + public void updateData() { + TreeModelUtil.setTextAndRepaint(dataTreeNode, "data [" + activeBranch.getBranchName() + "]"); + final IBranch branch = activeBranch.getBranch(); + PNodeAdapter rootNode = new PNodeAdapter(ITree.ROOT_ID, branch); + Iterable childTreeNodes = Sequence.fromIterable(TreeModelUtil.getChildren(dataTreeNode)).toListSequence(); + if (Sequence.fromIterable(childTreeNodes).count() != 1 || !(Objects.equals(((CloudNodeTreeNode) Sequence.fromIterable(childTreeNodes).first()).getNode(), rootNode))) { + CloudNodeTreeNode newTreeNode = new CloudNodeTreeNode(branch, rootNode); + TreeModelUtil.setChildren(dataTreeNode, ListSequence.fromListAndArray(new ArrayList(), newTreeNode)); + } + Sequence.fromIterable(TreeModelUtil.getChildren(dataTreeNode)).ofType(CloudNodeTreeNode.class).visitAll(new IVisitor() { + public void visit(CloudNodeTreeNode it) { + it.update(); + } + }); + } + + private static final class PROPS { + /*package*/ static final SProperty id$baYB = MetaAdapterFactory.getProperty(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, 0x62b7d9b07cecbcc6L, "id"); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink branches$b5_g = MetaAdapterFactory.getContainmentLink(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, 0x62b7d9b07cecbcc4L, "branches"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeModelUtil.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeModelUtil.java new file mode 100644 index 00000000..3b4d5f7e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeModelUtil.java @@ -0,0 +1,121 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import javax.swing.tree.TreeNode; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.Sequence; +import java.util.Objects; +import javax.swing.tree.DefaultTreeModel; +import jetbrains.mps.ide.ThreadUtils; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import javax.swing.tree.MutableTreeNode; +import jetbrains.mps.util.IterableUtil; +import javax.swing.tree.TreeModel; +import jetbrains.mps.ide.ui.tree.MPSTree; +import jetbrains.mps.ide.ui.tree.MPSTreeNode; +import javax.swing.tree.TreePath; + +public class TreeModelUtil { + public static void setChildren(TreeNode parent, Iterable children_) { + List children = Sequence.fromIterable(children_).toListSequence(); + if (Objects.equals(Sequence.fromIterable(getChildren(parent)).toListSequence(), children)) { + return; + } + boolean wasExpanded = isExpanded(parent); + clearChildren(parent); + DefaultTreeModel model = as_spdlqu_a0a4a0(getModel(parent), DefaultTreeModel.class); + if (model != null) { + ThreadUtils.assertEDT(); + int i = 0; + for (TreeNode child : ListSequence.fromList(children)) { + model.insertNodeInto((MutableTreeNode) child, (MutableTreeNode) parent, i); + i++; + } + } else { + int i = 0; + for (TreeNode child : ListSequence.fromList(children)) { + ((MutableTreeNode) parent).insert((MutableTreeNode) child, i); + i++; + } + } + if (wasExpanded) { + getTree(parent).expandPath(getPath(parent)); + } + } + public static Iterable getChildren(TreeNode parent) { + Iterable result = IterableUtil.asIterable(parent.children().asIterator()); + return Sequence.fromIterable(result).ofType(TreeNode.class); + } + + public static void clearChildren(TreeNode parent) { + DefaultTreeModel model = as_spdlqu_a0a0a3(getModel(parent), DefaultTreeModel.class); + if (model != null) { + ThreadUtils.assertEDT(); + while (model.getChildCount(parent) > 0) { + model.removeNodeFromParent((MutableTreeNode) model.getChild(parent, 0)); + } + } else { + while (parent.getChildCount() > 0) { + ((MutableTreeNode) parent).remove(0); + } + } + } + + public static TreeModel getModel(TreeNode node) { + return check_spdlqu_a0a5(getTree(node)); + } + + public static MPSTree getTree(TreeNode node) { + return (node instanceof MPSTreeNode ? ((MPSTreeNode) node).getTree() : null); + } + + public static void repaint(final TreeNode node) { + ThreadUtils.runInUIThreadAndWait(new Runnable() { + public void run() { + check_spdlqu_a0a0a0a9(getTree(node)); + } + }); + } + + public static void setTextAndRepaint(MPSTreeNode node, String text) { + node.setText(text); + repaint(node); + } + + public static boolean isExpanded(TreeNode node) { + return check_spdlqu_a0a31(getTree(node), node); + } + + public static TreePath getPath(TreeNode node) { + if (node.getParent() == null) { + return new TreePath(node); + } else { + return getPath(node.getParent()).pathByAddingChild(node); + } + } + private static DefaultTreeModel check_spdlqu_a0a5(MPSTree checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModel(); + } + return null; + } + private static void check_spdlqu_a0a0a0a9(MPSTree checkedDotOperand) { + if (null != checkedDotOperand) { + checkedDotOperand.repaint(); + } + + } + private static boolean check_spdlqu_a0a31(MPSTree checkedDotOperand, TreeNode node) { + if (null != checkedDotOperand) { + return checkedDotOperand.isExpanded(getPath(node)); + } + return false; + } + private static T as_spdlqu_a0a4a0(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + private static T as_spdlqu_a0a0a3(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeAccess.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeAccess.java new file mode 100644 index 00000000..36d01327 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeAccess.java @@ -0,0 +1,78 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import javax.swing.tree.TreeNode; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.modelix.model.api.INode; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.modelix.model.mpsplugin.ModelServerNavigation; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import org.modelix.model.mpsplugin.CloudRepository; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class TreeNodeAccess { + public TreeNodeAccess() { + } + public static String getName(final TreeNode _this) { + final CloudNodeTreeNode nodeTreeNode = as_ps3aya_a0a0a1(_this, CloudNodeTreeNode.class); + return new PArea(nodeTreeNode.getBranch()).executeRead(new Function0() { + public String invoke() { + return nodeTreeNode.getNode().getPropertyValue(PROPS.name$MnvL.getName()); + } + }); + } + public static void delete(final TreeNode _this) { + final CloudNodeTreeNode nodeTreeNode = as_ps3aya_a0a0a2(_this, CloudNodeTreeNode.class); + TreeNode parent = nodeTreeNode.getParent(); + new PArea(nodeTreeNode.getBranch()).executeWrite(new Function0() { + public Unit invoke() { + final INode nodeIN = nodeTreeNode.getNode(); + INode parent = nodeIN.getParent(); + if (parent == null) { + final Wrappers._boolean found = new Wrappers._boolean(false); + ListSequence.fromList(ModelServerNavigation.trees(nodeTreeNode.getModelServer())).visitAll(new IVisitor() { + public void visit(CloudRepository tree) { + if (ListSequence.fromList(tree.repoRoots()).contains(nodeIN)) { + tree.deleteRoot(nodeIN); + found.value = true; + } + } + }); + if (found.value) { + return Unit.INSTANCE; + } + if (!(found.value)) { + throw new RuntimeException("Unable to remove node without parent, not found as root of any tree"); + } + } + parent.removeChild(nodeIN); + return Unit.INSTANCE; + } + }); + + if (parent == null) { + throw new RuntimeException("Cannot remove node without parent"); + } + if (parent instanceof CloudNodeTreeNode) { + CloudNodeTreeNode parentCNTN = ((CloudNodeTreeNode) parent); + parentCNTN.remove(nodeTreeNode); + } else { + throw new RuntimeException("Unable to remove child from parent " + parent + " (" + parent.getClass() + ")"); + } + } + private static T as_ps3aya_a0a0a1(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + private static T as_ps3aya_a0a0a2(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeBinding.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeBinding.java new file mode 100644 index 00000000..a339b7b1 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeBinding.java @@ -0,0 +1,33 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.TransientModuleBinding; + +public class TreeNodeBinding { + public TreeNodeBinding() { + } + public static boolean isBoundAsModule(final TreeNode _this) { + CloudNodeTreeNode nodeTreeNode = as_qoya4i_a0a0a1(_this, CloudNodeTreeNode.class); + if (nodeTreeNode == null) { + return false; + } else { + return CloudNodeTreeNodeBinding.isBoundAsAModule(nodeTreeNode); + } + } + public static TransientModuleBinding getTransientModuleBinding(final TreeNode _this) { + CloudNodeTreeNode nodeTreeNode = as_qoya4i_a0a0a2(_this, CloudNodeTreeNode.class); + if (nodeTreeNode == null) { + return null; + } else { + return CloudNodeTreeNodeBinding.getTransientModuleBinding(nodeTreeNode); + } + } + private static T as_qoya4i_a0a0a1(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + private static T as_qoya4i_a0a0a2(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeClassification.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeClassification.java new file mode 100644 index 00000000..b3f59f62 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/TreeNodeClassification.java @@ -0,0 +1,50 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import javax.swing.tree.TreeNode; + +public class TreeNodeClassification { + public TreeNodeClassification() { + } + public static boolean isRootNode(final TreeNode _this) { + CloudNodeTreeNode nodeTreeNode = as_k32uer_a0a0a1(_this, CloudNodeTreeNode.class); + if (nodeTreeNode == null) { + return false; + } else { + return CloudNodeTreeNodeClassification.isCloudNodeRootNode(nodeTreeNode); + } + } + public static boolean isProperNode(final TreeNode _this) { + CloudNodeTreeNode nodeTreeNode = as_k32uer_a0a0a2(_this, CloudNodeTreeNode.class); + return nodeTreeNode != null; + } + public static boolean isModuleNode(final TreeNode _this) { + CloudNodeTreeNode nodeTreeNode = as_k32uer_a0a0a3(_this, CloudNodeTreeNode.class); + if (nodeTreeNode == null) { + return false; + } else { + return CloudNodeTreeNodeClassification.isCloudNodeModuleNode(nodeTreeNode); + } + } + public static boolean isProjectNode(final TreeNode _this) { + CloudNodeTreeNode nodeTreeNode = as_k32uer_a0a0a4(_this, CloudNodeTreeNode.class); + if (nodeTreeNode == null) { + return false; + } else { + return CloudNodeTreeNodeClassification.isCloudNodeAProjectNode(nodeTreeNode); + } + } + private static T as_k32uer_a0a0a1(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + private static T as_k32uer_a0a0a2(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + private static T as_k32uer_a0a0a3(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + private static T as_k32uer_a0a0a4(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/_Adapters.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/_Adapters.java new file mode 100644 index 00000000..7bee7733 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/_Adapters.java @@ -0,0 +1,17 @@ +package org.modelix.model.mpsplugin.history; + +/*Generated by MPS */ + +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; + +public class _Adapters { + public static class _return_P0_E0_to_Runnable_adapter implements Runnable { + private _FunctionTypes._return_P0_E0 adapted; + public _return_P0_E0_to_Runnable_adapter(_FunctionTypes._return_P0_E0 adapted) { + this.adapted = adapted; + } + public void run() { + this.adapted.invoke(); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/trace.info b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/trace.info new file mode 100644 index 00000000..aa28befc --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/history/trace.info @@ -0,0 +1,1728 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddBranch_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddBranch_Action.java new file mode 100644 index 00000000..e2063166 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddBranch_Action.java @@ -0,0 +1,110 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.history.CloudBranchTreeNode; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.api.IBranch; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.jetbrains.mps.openapi.model.SNode; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import java.util.Objects; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; +import org.modelix.model.mpsadapters.mps.SNodeAPI; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SConcept; + +public class AddBranch_Action extends BaseAction { + private static final Icon ICON = null; + + public AddBranch_Action() { + super("New Branch", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + final String name = Messages.showInputDialog(event.getData(CommonDataKeys.PROJECT), "Name", "Add Branch", null); + if ((name == null || name.length() == 0)) { + return; + } + final CloudBranchTreeNode branchTreeNode = ((CloudBranchTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)); + final RepositoryTreeNode treeTreeNode = branchTreeNode.getAncestor(RepositoryTreeNode.class); + final RepositoryId repositoryId = treeTreeNode.getRepositoryId(); + final ModelServerConnection modelServer = treeTreeNode.getModelServer(); + final IBranch infoBranch = modelServer.getInfoBranch(); + new PArea(infoBranch).executeWrite(new Function0() { + public Unit invoke() { + SNode treeInfo = treeTreeNode.getRepositoryInfo(); + if (ListSequence.fromList(SLinkOperations.getChildren(treeInfo, LINKS.branches$b5_g)).any(new IWhereFilter() { + public boolean accept(SNode it) { + return Objects.equals(SPropertyOperations.getString(it, PROPS.name$MnvL), name); + } + })) { + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "Branch '" + name + "' already exists", "Add Branch"); + return Unit.INSTANCE; + } + String versionHash = modelServer.getClient().get(repositoryId.getBranchKey(SPropertyOperations.getString(branchTreeNode.getBranchInfo(), PROPS.name$MnvL))); + modelServer.getClient().put(repositoryId.getBranchKey(name), versionHash); + + SNode branchInfo = SNodeOperations.cast(SNodeAPI.addNewChild(treeInfo, LINKS.branches$b5_g), CONCEPTS.BranchInfo$6t); + SPropertyOperations.assign(branchInfo, PROPS.name$MnvL, name); + return Unit.INSTANCE; + } + }); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink branches$b5_g = MetaAdapterFactory.getContainmentLink(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, 0x62b7d9b07cecbcc4L, "branches"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept BranchInfo$6t = MetaAdapterFactory.getConcept(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc1L, "org.modelix.model.runtimelang.structure.BranchInfo"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddChildNode_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddChildNode_Action.java new file mode 100644 index 00000000..78afae96 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddChildNode_Action.java @@ -0,0 +1,135 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import kotlin.Unit; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class AddChildNode_Action extends BaseAction { + private static final Icon ICON = null; + + private INode parentNode; + private SAbstractConcept childConcept; + private SContainmentLink role; + public AddChildNode_Action(INode parentNode_par, SAbstractConcept childConcept_par, SContainmentLink role_par) { + super("Add new child of concept ... in role ...", "", ICON); + this.parentNode = parentNode_par; + this.childConcept = childConcept_par; + this.role = role_par; + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.NONE); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + if (AddChildNode_Action.this.childConcept == null) { + event.getPresentation().setText("To '" + AddChildNode_Action.this.role.getName()); + } else { + event.getPresentation().setText("To '" + AddChildNode_Action.this.role.getName() + "' add '" + AddChildNode_Action.this.childConcept.getLanguage().getQualifiedName() + "." + AddChildNode_Action.this.childConcept.getName() + "'"); + } + return true; + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + + final Wrappers._T name = new Wrappers._T(null); + if (AddChildNode_Action.this.childConcept.getProperties().contains(PROPS.name$MnvL)) { + name.value = Messages.showInputDialog(event.getData(CommonDataKeys.PROJECT), "Name", "Add " + AddChildNode_Action.this.childConcept.getName(), null); + if (isEmptyString(name.value)) { + return; + } + } + + new PArea(nodeTreeNode.getBranch()).executeWrite(new Function0() { + public Unit invoke() { + INode newModule = AddChildNode_Action.this.parentNode.addNewChild(AddChildNode_Action.this.role.getName(), -1, SConceptAdapter.wrap(AddChildNode_Action.this.childConcept)); + if (isNotEmptyString(name.value)) { + newModule.setPropertyValue(PROPS.name$MnvL.getName(), name.value); + } + return Unit.INSTANCE; + } + }); + } + @NotNull + public String getActionId() { + StringBuilder res = new StringBuilder(); + res.append(super.getActionId()); + res.append("#"); + res.append(parentNode_State((INode) this.parentNode)); + res.append("!"); + res.append(childConcept_State((SAbstractConcept) this.childConcept)); + res.append("!"); + res.append(role_State((SContainmentLink) this.role)); + res.append("!"); + return res.toString(); + } + public static String parentNode_State(INode object) { + return object.toString(); + } + public static String childConcept_State(SAbstractConcept object) { + if (object == null) { + return "null"; + } + return object.getName(); + } + public static String role_State(SContainmentLink object) { + return object.getName(); + } + private static boolean isEmptyString(String str) { + return str == null || str.isEmpty(); + } + private static boolean isNotEmptyString(String str) { + return str != null && str.length() > 0; + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModelNode_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModelNode_Action.java new file mode 100644 index 00000000..d9d8c210 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModelNode_Action.java @@ -0,0 +1,69 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.CloudNodeTreeNodeCreationMethods; + +public class AddModelNode_Action extends BaseAction { + private static final Icon ICON = null; + + public AddModelNode_Action() { + super("Add Model", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isModuleNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + + String name = Messages.showInputDialog(event.getData(CommonDataKeys.PROJECT), "Name", "Add Model", null); + if ((name == null || name.length() == 0)) { + return; + } + + CloudNodeTreeNodeCreationMethods.createModel(nodeTreeNode, name); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModelServer_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModelServer_Action.java new file mode 100644 index 00000000..2a5bd48e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModelServer_Action.java @@ -0,0 +1,82 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.ui.Messages; +import jetbrains.mps.baseLanguage.logging.runtime.model.LoggingRuntime; +import org.apache.log4j.Level; +import jetbrains.mps.ide.project.ProjectHelper; +import org.modelix.model.mpsplugin.ModelServerConnections; +import org.modelix.authentication.plugin.AuthenticationManager; +import java.util.function.Consumer; +import org.modelix.model.mpsplugin.ModelServerConnection; + +public class AddModelServer_Action extends BaseAction { + private static final Logger LOG = LogManager.getLogger(AddModelServer_Action.class); + private static final Icon ICON = null; + + public AddModelServer_Action() { + super("Add Model Server", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + String url = Messages.showInputDialog(event.getData(CommonDataKeys.PROJECT), "URL", "Add Model Server", null, "http://", null); + if (!(url.toLowerCase().startsWith("http://")) && !(url.toLowerCase().startsWith("https://"))) { + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "Invalid URL: it should shart with http:// or https://", "Add Model Server"); + return; + } + if (url != null && (url != null && url.length() > 0)) { + if (!(url.endsWith("/"))) { + String originalUrl = url; + url = url + "/"; + LoggingRuntime.logMsgView(Level.INFO, "A Model Server URL should end with a slash. URL modified from '" + originalUrl + "' to '" + url + "'", AddModelServer_Action.class, null, ProjectHelper.fromIdeaProject(event.getData(CommonDataKeys.PROJECT))); + } + if (ModelServerConnections.getInstance().existModelServer(url)) { + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "Already present!", "Add Model Server"); + return; + } + String token = null; + final String finalUrl = url; + if (AuthenticationManager.getAuthenticationProcess(finalUrl).areWeUsingAuthentication(event.getData(CommonDataKeys.PROJECT))) { + AuthenticationManager.getAuthenticationProcess(finalUrl).getToken(event.getData(CommonDataKeys.PROJECT), new Consumer() { + @Override + public void accept(String token) { + ModelServerConnection modelServer = ModelServerConnections.getInstance().ensureModelServerIsPresent(finalUrl); + PersistedBindingConfiguration.getInstance(event.getData(CommonDataKeys.PROJECT)).ensureModelServerIsPresent(modelServer); + } + }); + } else { + ModelServerConnection modelServer = ModelServerConnections.getInstance().ensureModelServerIsPresent(finalUrl); + PersistedBindingConfiguration.getInstance(event.getData(CommonDataKeys.PROJECT)).ensureModelServerIsPresent(modelServer); + } + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModuleNode_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModuleNode_Action.java new file mode 100644 index 00000000..ceca394f --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddModuleNode_Action.java @@ -0,0 +1,69 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.CloudNodeTreeNodeCreationMethods; + +public class AddModuleNode_Action extends BaseAction { + private static final Icon ICON = null; + + public AddModuleNode_Action() { + super("Add Module", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isRootNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + + String name = Messages.showInputDialog(event.getData(CommonDataKeys.PROJECT), "Name", "Add Module", null); + if ((name == null || name.length() == 0)) { + return; + } + + CloudNodeTreeNodeCreationMethods.createModule(nodeTreeNode, name); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddProjectBinding_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddProjectBinding_Action.java new file mode 100644 index 00000000..598438cc --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddProjectBinding_Action.java @@ -0,0 +1,105 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.project.MPSProject; +import javax.swing.tree.TreeNode; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import java.util.Objects; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.mpsplugin.history.ModelServerTreeNode; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.mpsplugin.ModelCloudImportUtils; +import org.modelix.model.mpsplugin.SyncDirection; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class AddProjectBinding_Action extends BaseAction { + private static final Icon ICON = null; + + public AddProjectBinding_Action() { + super("Bind to Current Project", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + if (!(TreeNodeClassification.isProjectNode(event.getData(MPSCommonDataKeys.TREE_NODE)))) { + return false; + } + CloudNodeTreeNode nodeTreeNode = as_8zbn8k_a0a1a4(event.getData(MPSCommonDataKeys.TREE_NODE), CloudNodeTreeNode.class); + long nodeId = ((PNodeAdapter) nodeTreeNode.getNode()).getNodeId(); + RepositoryId repositoryId = nodeTreeNode.getAncestor(RepositoryTreeNode.class).getRepositoryId(); + if (nodeTreeNode.getModelServer().hasProjectBinding(repositoryId, nodeId)) { + return false; + } + return true; + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + MPSProject p = event.getData(MPSCommonDataKeys.MPS_PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + final CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + String expectedProjectName = new PArea(nodeTreeNode.getBranch()).executeRead(new Function0() { + public String invoke() { + return nodeTreeNode.getNode().getPropertyValue(PROPS.name$MnvL.getName()); + } + }); + if (!(Objects.equals(expectedProjectName, event.getData(MPSCommonDataKeys.MPS_PROJECT).getName()))) { + int dialogResult = Messages.showOkCancelDialog(event.getData(MPSCommonDataKeys.MPS_PROJECT).getProject(), "Project names don't match. Do you want to bind '" + expectedProjectName + "' to '" + event.getData(MPSCommonDataKeys.MPS_PROJECT).getName() + "'?", "Bind Project", null); + if (dialogResult != Messages.OK) { + return; + } + } + ModelServerConnection modelServer = nodeTreeNode.getAncestor(ModelServerTreeNode.class).getModelServer(); + RepositoryId repositoryId = nodeTreeNode.getAncestor(RepositoryTreeNode.class).getRepositoryId(); + CloudRepository treeInRepository = new CloudRepository(modelServer, repositoryId); + long cloudProjectId = ((PNodeAdapter) nodeTreeNode.getNode()).getNodeId(); + ModelCloudImportUtils.bindCloudProjectToMpsProject(treeInRepository, cloudProjectId, event.getData(MPSCommonDataKeys.MPS_PROJECT), SyncDirection.TO_MPS); + } + private static T as_8zbn8k_a0a1a4(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddProjectNode_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddProjectNode_Action.java new file mode 100644 index 00000000..56ac2c3d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddProjectNode_Action.java @@ -0,0 +1,69 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.CloudNodeTreeNodeCreationMethods; + +public class AddProjectNode_Action extends BaseAction { + private static final Icon ICON = null; + + public AddProjectNode_Action() { + super("Add Project", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isRootNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + + String name = Messages.showInputDialog(event.getData(CommonDataKeys.PROJECT), "Name", "Add Project", null); + if ((name == null || name.length() == 0)) { + return; + } + + CloudNodeTreeNodeCreationMethods.createProject(nodeTreeNode, name); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddRepository_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddRepository_Action.java new file mode 100644 index 00000000..07d780b3 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddRepository_Action.java @@ -0,0 +1,69 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.ModelServerTreeNode; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.CloudIcons; +import jetbrains.mps.util.NameUtil; + +public class AddRepository_Action extends BaseAction { + private static final Icon ICON = null; + + public AddRepository_Action() { + super("Add Repository", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return event.getData(MPSCommonDataKeys.TREE_NODE) instanceof ModelServerTreeNode; + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + ModelServerConnection modelServer = ((ModelServerTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)).getModelServer(); + + String id = Messages.showInputDialog(event.getData(CommonDataKeys.PROJECT), "ID", "Add Repository", CloudIcons.REPOSITORY_ICON); + if ((id == null || id.length() == 0)) { + return; + } + modelServer.addRepository(NameUtil.toValidIdentifier(id)); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddTransientModuleBinding_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddTransientModuleBinding_Action.java new file mode 100644 index 00000000..ffc7165b --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AddTransientModuleBinding_Action.java @@ -0,0 +1,78 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.TreeNodeBinding; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.TransientModuleBinding; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.mpsplugin.history.ModelServerTreeNode; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.mpsplugin.CloudRepository; + +public class AddTransientModuleBinding_Action extends BaseAction { + private static final Icon ICON = null; + + public AddTransientModuleBinding_Action() { + super("Bind to Transient Module", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isModuleNode(event.getData(MPSCommonDataKeys.TREE_NODE)) && !(TreeNodeBinding.isBoundAsModule(event.getData(MPSCommonDataKeys.TREE_NODE))); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + AddTransientModuleBinding_Action.this.addTransientModuleBinding(event.getData(MPSCommonDataKeys.TREE_NODE), event.getData(CommonDataKeys.PROJECT), event); + } + public TransientModuleBinding addTransientModuleBinding(TreeNode treeNode, Project mpsProject, final AnActionEvent event) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) treeNode; + ModelServerConnection modelServerConnection = nodeTreeNode.getAncestor(ModelServerTreeNode.class).getModelServer(); + RepositoryId repositoryId = nodeTreeNode.getAncestor(RepositoryTreeNode.class).getRepositoryId(); + TransientModuleBinding transientModuleBinding = new TransientModuleBinding(((PNodeAdapter) nodeTreeNode.getNode()).getNodeId()); + modelServerConnection.addBinding(repositoryId, transientModuleBinding); + CloudRepository treeInRepository = new CloudRepository(modelServerConnection, repositoryId); + PersistedBindingConfiguration.getInstance(mpsProject).addTransientBoundModule(treeInRepository, nodeTreeNode); + return transientModuleBinding; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ApplicationPlugin_AppPluginPart.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ApplicationPlugin_AppPluginPart.java new file mode 100644 index 00000000..731aeb44 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ApplicationPlugin_AppPluginPart.java @@ -0,0 +1,129 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.part.ApplicationPluginPart; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.common.PropertyOrEnv; +import org.modelix.model.mpsplugin.ModelServerConnections; +import org.modelix.model.lazy.RepositoryId; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.apache.log4j.Level; +import org.modelix.model.mpsplugin.MpsReplicatedRepository; +import org.modelix.model.mpsplugin.CloudTransientModules; +import org.modelix.model.mpsplugin.SharedExecutors; + +public class ApplicationPlugin_AppPluginPart extends ApplicationPluginPart { + private static final Logger LOG = LogManager.getLogger(ApplicationPlugin_AppPluginPart.class); + private AutoBindings autoBindings; + public ApplicationPlugin_AppPluginPart() { + } + @Override + public void init() { + System.out.println("Modelix Application Plugin - Started"); + System.out.flush(); + MetaMetaModelMappings.register(); + try { + EModelixExecutionMode executionMode = ModelixConfigurationSystemProperties.getExecutionMode(); + System.out.println("Modelix Application Plugin - execution mode: " + executionMode); + + if (executionMode == EModelixExecutionMode.CLUSTER || executionMode == EModelixExecutionMode.PROJECTOR) { + String modelUri = PropertyOrEnv.get("MODEL_URI"); + if ((modelUri != null && modelUri.length() > 0)) { + ModelServerConnections.getInstance().addModelServer(modelUri); + } + + String repositoryId = PropertyOrEnv.get("REPOSITORY_ID"); + Iterable fixedRepositoryIds = null; + boolean bindProjects = executionMode == EModelixExecutionMode.PROJECTOR; + if ((repositoryId != null && repositoryId.length() > 0)) { + fixedRepositoryIds = Sequence.singleton(new RepositoryId(repositoryId)); + } + ApplicationPlugin_AppPluginPart.this.autoBindings = new AutoBindings(ModelServerConnections.getInstance(), fixedRepositoryIds, bindProjects); + } + + switch (executionMode) { + case CLUSTER: + + + break; + case PROJECTOR: + + break; + case INTEGRATION_TESTS: + + break; + case MODEL_EXPORT: + new ModelImportExport().cloud2mps(); + break; + case MODEL_IMPORT: + new ModelImportExport().mps2cloud(); + break; + case DEFAULT: + String cloudReposSpecified = PropertyOrEnv.get(ModelixConfigurationSystemProperties.CLOUD_REPOS_SYSPROP); + if (cloudReposSpecified != null && (cloudReposSpecified != null && cloudReposSpecified.length() > 0)) { + String[] repos = cloudReposSpecified.split(","); + for (String repo : repos) { + ModelServerConnections.getInstance().addModelServer(repo); + } + } + break; + default: + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Unknown execution mode: " + executionMode); + } + break; + } + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + @Override + public void dispose() { + MetaMetaModelMappings.unregister(); + try { + MpsReplicatedRepository.disposeAll(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + + try { + if (ApplicationPlugin_AppPluginPart.this.autoBindings != null) { + ApplicationPlugin_AppPluginPart.this.autoBindings.dispose(); + } + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + + try { + ModelServerConnections.getInstance().dispose(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + + try { + CloudTransientModules.getInstance().dispose(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + + try { + SharedExecutors.shutdownAll(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AutoBindings.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AutoBindings.java new file mode 100644 index 00000000..b0c9da81 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/AutoBindings.java @@ -0,0 +1,301 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import org.modelix.model.mpsplugin.ModelServerConnections; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.api.IBranchListener; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import java.util.Set; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import org.modelix.model.client.ActiveBranch; +import java.util.List; +import org.modelix.model.lazy.RepositoryId; +import java.util.concurrent.ScheduledFuture; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.modelix.model.mpsplugin.SharedExecutors; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import org.modelix.model.api.IBranch; +import org.modelix.model.api.ITree; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import org.jetbrains.mps.openapi.model.SNode; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import jetbrains.mps.internal.collections.runtime.IListSequence; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import kotlin.Unit; +import org.modelix.model.api.ITransaction; +import org.modelix.model.mpsadapters.mps.NodeToSNodeAdapter; +import org.modelix.model.api.PNodeAdapter; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; +import jetbrains.mps.lang.core.behavior.INamedConcept__BehaviorDescriptor; +import org.modelix.model.mpsadapters.mps.SNodeToNodeAdapter; +import jetbrains.mps.project.Project; +import jetbrains.mps.project.ProjectManager; +import org.modelix.model.mpsplugin.ProjectBinding; +import jetbrains.mps.project.MPSProject; +import org.modelix.model.mpsplugin.TransientModuleBinding; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SConcept; + +public class AutoBindings implements ModelServerConnections.IListener, ModelServerConnection.IListener, IBranchListener { + private static final Logger LOG = LogManager.getLogger(AutoBindings.class); + + private ModelServerConnections repositories; + private Set subscribedModelServers = SetSequence.fromSet(new HashSet()); + private Set subscribedInfoBranches = SetSequence.fromSet(new HashSet()); + private Set subscribedActiveBranches = SetSequence.fromSet(new HashSet()); + private volatile boolean requiresUpdate = false; + private List fixedRepositories; + private boolean bindProjects; + private ScheduledFuture updateJob; + + public AutoBindings(ModelServerConnections repositories) { + this(repositories, null, false); + } + + public AutoBindings(ModelServerConnections repositories, Iterable fixedRepositoryIds, boolean bindProjects) { + if (LOG.isDebugEnabled()) { + LOG.debug("AutoBindings.init"); + } + this.repositories = repositories; + this.fixedRepositories = (fixedRepositoryIds == null ? null : Sequence.fromIterable(fixedRepositoryIds).toListSequence()); + this.bindProjects = bindProjects; + repositories.addListener(this); + subscribeToServers(); + if (fixedRepositories == null) { + subscribeToInfoBranches(); + } + updateBindingsLater(); + updateJob = SharedExecutors.fixDelay(500, new Runnable() { + public void run() { + if (requiresUpdate) { + requiresUpdate = false; + updateBindings(); + } + } + }); + } + + @Override + public void repositoriesChanged() { + if (LOG.isDebugEnabled()) { + LOG.debug("AutoBindings.repositoriesChanged"); + } + subscribeToServers(); + subscribeToInfoBranches(); + updateBindingsLater(); + } + + protected void subscribeToServers() { + for (ModelServerConnection server : Sequence.fromIterable(repositories.getModelServers()).where(new IWhereFilter() { + public boolean accept(ModelServerConnection it) { + return !(SetSequence.fromSet(subscribedModelServers).contains(it)); + } + })) { + server.addListener(this); + SetSequence.fromSet(subscribedModelServers).addElement(server); + } + } + + @Override + public void connectionStatusChanged(boolean connected) { + if (LOG.isDebugEnabled()) { + LOG.debug("AutoBindings.connectionStatusChanged, " + connected); + } + subscribeToInfoBranches(); + updateBindingsLater(); + } + + protected void subscribeToInfoBranches() { + for (ModelServerConnection repo : SetSequence.fromSet(subscribedModelServers).subtract(SetSequence.fromSet(subscribedInfoBranches)).where(new IWhereFilter() { + public boolean accept(ModelServerConnection it) { + return it.isConnected(); + } + })) { + IBranch infoBranch = repo.getInfoBranch(); + if (infoBranch != null) { + infoBranch.addListener(this); + SetSequence.fromSet(subscribedInfoBranches).addElement(repo); + } + } + } + + @Override + public void treeChanged(ITree oldTree, ITree newTree) { + updateBindingsLater(); + } + + public void updateBindingsLater() { + requiresUpdate = true; + } + + protected synchronized void updateBindings() { + if (LOG.isDebugEnabled()) { + LOG.debug("AutoBindings.updateBindings"); + } + + List allActiveBranches = ListSequence.fromList(new ArrayList()); + + for (final ModelServerConnection connection : Sequence.fromIterable(repositories.getModelServers()).where(new IWhereFilter() { + public boolean accept(ModelServerConnection it) { + return it.isConnected(); + } + })) { + if (LOG.isDebugEnabled()) { + LOG.debug("update bindings for " + connection.getBaseUrl()); + } + List repositories; + if (fixedRepositories == null) { + final SNode info = connection.getInfo(); + repositories = new PArea(connection.getInfoBranch()).executeRead(new Function0>() { + public IListSequence invoke() { + return ListSequence.fromList(SLinkOperations.getChildren(info, LINKS.repositories$b56J)).select(new ISelector() { + public RepositoryId select(SNode it) { + return new RepositoryId(SPropertyOperations.getString(it, PROPS.id$baYB)); + } + }).toListSequence(); + } + }); + } else { + repositories = fixedRepositories; + } + if (LOG.isDebugEnabled()) { + LOG.debug("using repositories: " + ListSequence.fromList(repositories).select(new ISelector() { + public String select(RepositoryId it) { + return it.getId(); + } + })); + } + for (final RepositoryId repositoryId : ListSequence.fromList(repositories)) { + final ActiveBranch activeBranch = connection.getActiveBranch(repositoryId); + if (LOG.isDebugEnabled()) { + LOG.debug("using branch: " + activeBranch.getBranchName()); + } + ListSequence.fromList(allActiveBranches).addElement(activeBranch); + final List<_FunctionTypes._void_P0_E0> outsideRead = ListSequence.fromList(new ArrayList<_FunctionTypes._void_P0_E0>()); + new PArea(activeBranch.getBranch()).executeRead(new Function0() { + public Unit invoke() { + ITransaction t = activeBranch.getBranch().getTransaction(); + Iterable allChildren_ = t.getAllChildren(ITree.ROOT_ID); + Iterable allChildren = Sequence.fromIterable(allChildren_).select(new ISelector() { + public SNode select(Long it) { + SNode n = NodeToSNodeAdapter.wrap(PNodeAdapter.Companion.wrap(it, activeBranch.getBranch())); + return n; + } + }); + + Iterable allProjects = SNodeOperations.ofConcept(allChildren, CONCEPTS.Project$An); + Iterable remainingProjects = allProjects; + if (bindProjects) { + SNode firstProject = Sequence.fromIterable(allProjects).first(); + if (LOG.isDebugEnabled()) { + LOG.debug("trying to bind project: " + INamedConcept__BehaviorDescriptor.getFqName_idhEwIO9y.invoke(firstProject)); + } + remainingProjects = Sequence.fromIterable(allProjects).skip(1); + final long projectNodeId = (firstProject == null ? 0L : ((PNodeAdapter) SNodeToNodeAdapter.wrap(firstProject)).getNodeId()); + final List mpsProjects = ProjectManager.getInstance().getOpenedProjects(); + if (ListSequence.fromList(mpsProjects).isNotEmpty()) { + if (LOG.isDebugEnabled()) { + LOG.debug("mps projects found: " + ListSequence.fromList(mpsProjects).select(new ISelector() { + public String select(Project it) { + return it.getName(); + } + })); + } + if (!(connection.hasProjectBinding(repositoryId, projectNodeId))) { + if (LOG.isDebugEnabled()) { + LOG.debug("adding project binding"); + } + if (projectNodeId != 0L && ListSequence.fromList(SLinkOperations.getChildren(firstProject, LINKS.modules$Bi3g)).isEmpty()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Server side project doesn't contain any modules"); + } + } + ListSequence.fromList(outsideRead).addElement(new _FunctionTypes._void_P0_E0() { + public void invoke() { + connection.addBinding(repositoryId, new ProjectBinding((MPSProject) ListSequence.fromList(mpsProjects).first(), projectNodeId, null)); + } + }); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("no mps project found yet"); + } + updateBindingsLater(); + } + } + + Iterable modules = Sequence.fromIterable(SNodeOperations.ofConcept(allChildren, CONCEPTS.Module$4i)).concat(Sequence.fromIterable(SLinkOperations.collectMany(remainingProjects, LINKS.modules$Bi3g))); + for (SNode module : Sequence.fromIterable(modules)) { + final long moduleNodeId = ((PNodeAdapter) SNodeToNodeAdapter.wrap(module)).getNodeId(); + if (connection.hasModuleBinding(repositoryId, moduleNodeId)) { + continue; + } + ListSequence.fromList(outsideRead).addElement(new _FunctionTypes._void_P0_E0() { + public void invoke() { + connection.addBinding(repositoryId, new TransientModuleBinding(moduleNodeId)); + } + }); + } + return Unit.INSTANCE; + } + }); + ListSequence.fromList(outsideRead).visitAll(new IVisitor<_FunctionTypes._void_P0_E0>() { + public void visit(_FunctionTypes._void_P0_E0 it) { + it.invoke(); + } + }); + } + } + + for (ActiveBranch newBranch : ListSequence.fromList(allActiveBranches).subtract(SetSequence.fromSet(subscribedActiveBranches)).toListSequence()) { + newBranch.addListener(this); + } + + for (ActiveBranch removedBranch : SetSequence.fromSet(subscribedActiveBranches).subtract(ListSequence.fromList(allActiveBranches)).toListSequence()) { + removedBranch.removeListener(this); + SetSequence.fromSet(subscribedActiveBranches).removeElement(removedBranch); + } + } + + public void dispose() { + check_7p0tz2_a0a82(updateJob); + for (ModelServerConnection repo : SetSequence.fromSet(subscribedInfoBranches)) { + repo.getInfoBranch().removeListener(this); + } + for (ModelServerConnection repo : SetSequence.fromSet(subscribedModelServers)) { + repo.removeListener(this); + } + repositories.removeListener(this); + } + private static boolean check_7p0tz2_a0a82(ScheduledFuture checkedDotOperand) { + if (null != checkedDotOperand) { + return checkedDotOperand.cancel(false); + } + return false; + } + + private static final class LINKS { + /*package*/ static final SContainmentLink repositories$b56J = MetaAdapterFactory.getContainmentLink(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcbfL, 0x62b7d9b07cecbcc2L, "repositories"); + /*package*/ static final SContainmentLink modules$Bi3g = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, 0x37a0917d689de9e2L, "modules"); + } + + private static final class PROPS { + /*package*/ static final SProperty id$baYB = MetaAdapterFactory.getProperty(0xb6980ebdf01d459dL, 0xa95238740f6313b4L, 0x62b7d9b07cecbcc0L, 0x62b7d9b07cecbcc6L, "id"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Project$An = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, "org.modelix.model.repositoryconcepts.structure.Project"); + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CheckoutAndSyncModule_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CheckoutAndSyncModule_Action.java new file mode 100644 index 00000000..7f847649 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CheckoutAndSyncModule_Action.java @@ -0,0 +1,61 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.ModelCloudImportUtils; +import jetbrains.mps.ide.project.ProjectHelper; + +public class CheckoutAndSyncModule_Action extends BaseAction { + private static final Icon ICON = null; + + public CheckoutAndSyncModule_Action() { + super("Checkout and Sync", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isModuleNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + ModelCloudImportUtils.checkoutAndSync(event.getData(MPSCommonDataKeys.TREE_NODE), ProjectHelper.toMPSProject(event.getData(CommonDataKeys.PROJECT))); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CheckoutModule_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CheckoutModule_Action.java new file mode 100644 index 00000000..4b445908 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CheckoutModule_Action.java @@ -0,0 +1,69 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNodeBinding; +import jetbrains.mps.ide.project.ProjectHelper; +import org.modelix.model.mpsplugin.ModuleCheckout; +import org.modelix.model.api.PNodeAdapter; + +public class CheckoutModule_Action extends BaseAction { + private static final Icon ICON = null; + + public CheckoutModule_Action() { + super("Checkout", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + // TODO verify it does not exist a module with such name + return TreeNodeClassification.isModuleNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + CloudRepository treeInRepository = CloudNodeTreeNodeBinding.getTreeInRepository(nodeTreeNode); + jetbrains.mps.project.Project mpsProject = ProjectHelper.toMPSProject(event.getData(CommonDataKeys.PROJECT)); + new ModuleCheckout(mpsProject, treeInRepository).checkoutCloudModule(((PNodeAdapter) nodeTreeNode.getNode())); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalModulesCloudActions_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalModulesCloudActions_ActionGroup.java new file mode 100644 index 00000000..b4c2abbd --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalModulesCloudActions_ActionGroup.java @@ -0,0 +1,47 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import java.util.Set; +import com.intellij.openapi.util.Pair; +import jetbrains.mps.workbench.ActionPlace; +import org.jetbrains.mps.util.Condition; +import jetbrains.mps.workbench.action.BaseAction; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; +import com.intellij.openapi.actionSystem.AnActionEvent; +import org.modelix.model.mpsplugin.CloudRepository; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.modelix.model.mpsplugin.ModelServerConnections; +import org.jetbrains.annotations.Nullable; + +public class CloudActionsForPhysicalModulesCloudActions_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudActionsForPhysicalModulesCloudActions_ActionGroup"; + private final Set>> myPlaces = SetSequence.fromSet(new HashSet>>()); + + public CloudActionsForPhysicalModulesCloudActions_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("Cloud Actions", ID, plugin); + setIsInternal(false); + setPopup(true); + } + public void doUpdate(AnActionEvent event) { + removeAll(); + for (CloudRepository treeInRepository : Sequence.fromIterable(ModelServerConnections.getInstance().getConnectedTreesInRepositories())) { + CloudActionsForPhysicalModulesCloudActions_ActionGroup.this.addParameterizedAction(new CopyAndSyncPhysicalModuleOnCloud_Action(treeInRepository), treeInRepository); + CloudActionsForPhysicalModulesCloudActions_ActionGroup.this.addParameterizedAction(new CopyPhysicalModuleOnCloud_Action(treeInRepository), treeInRepository); + CloudActionsForPhysicalModulesCloudActions_ActionGroup.this.addParameterizedAction(new ModuleAlreadyOnCloud_Action(treeInRepository), treeInRepository); + } + for (Pair> p : this.myPlaces) { + this.addPlace(p.first, p.second); + } + } + public void addPlace(ActionPlace place, @Nullable Condition cond) { + SetSequence.fromSet(this.myPlaces).addElement(new Pair>(place, cond)); + } + public boolean isStrict() { + return false; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalModules_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalModules_ActionGroup.java new file mode 100644 index 00000000..2e31a238 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalModules_ActionGroup.java @@ -0,0 +1,30 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; +import com.intellij.openapi.actionSystem.ex.ActionManagerEx; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.extensions.PluginId; + +public class CloudActionsForPhysicalModules_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudActionsForPhysicalModules_ActionGroup"; + + public CloudActionsForPhysicalModules_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("CloudActionsForPhysicalModules", ID, plugin); + setIsInternal(false); + setPopup(false); + { + GeneratedActionGroup newAction = new CloudActionsForPhysicalModulesCloudActions_ActionGroup(getApplicationPlugin()); + ActionManagerEx manager = ActionManagerEx.getInstanceEx(); + AnAction oldAction = manager.getAction(newAction.getId()); + if (oldAction == null) { + manager.registerAction(newAction.getId(), newAction, PluginId.getId("org.modelix.model.mpsplugin")); + oldAction = newAction; + } + CloudActionsForPhysicalModules_ActionGroup.this.addAction(oldAction); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalProjectsCloudActions_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalProjectsCloudActions_ActionGroup.java new file mode 100644 index 00000000..9e468980 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalProjectsCloudActions_ActionGroup.java @@ -0,0 +1,52 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import java.util.Set; +import com.intellij.openapi.util.Pair; +import jetbrains.mps.workbench.ActionPlace; +import org.jetbrains.mps.util.Condition; +import jetbrains.mps.workbench.action.BaseAction; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; +import com.intellij.openapi.actionSystem.AnActionEvent; +import org.modelix.model.mpsplugin.CloudRepository; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.modelix.model.mpsplugin.ModelServerConnections; +import java.util.function.Consumer; +import org.jetbrains.mps.openapi.model.SNode; +import org.jetbrains.annotations.Nullable; + +public class CloudActionsForPhysicalProjectsCloudActions_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudActionsForPhysicalProjectsCloudActions_ActionGroup"; + private final Set>> myPlaces = SetSequence.fromSet(new HashSet>>()); + + public CloudActionsForPhysicalProjectsCloudActions_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("Cloud Actions", ID, plugin); + setIsInternal(false); + setPopup(true); + } + public void doUpdate(AnActionEvent event) { + removeAll(); + for (final CloudRepository treeInRepository : Sequence.fromIterable(ModelServerConnections.getInstance().getConnectedTreesInRepositories())) { + treeInRepository.processProjects(new Consumer() { + public void accept(SNode pr) { + CloudActionsForPhysicalProjectsCloudActions_ActionGroup.this.addParameterizedAction(new CopyAndSyncPhysicalProjectOnCloud_Action(treeInRepository, pr), treeInRepository, pr); + } + }); + CloudActionsForPhysicalProjectsCloudActions_ActionGroup.this.addParameterizedAction(new CopyAndSyncPhysicalProjectOnCloud_Action(treeInRepository, null), treeInRepository, null); + } + for (Pair> p : this.myPlaces) { + this.addPlace(p.first, p.second); + } + } + public void addPlace(ActionPlace place, @Nullable Condition cond) { + SetSequence.fromSet(this.myPlaces).addElement(new Pair>(place, cond)); + } + public boolean isStrict() { + return false; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalProjects_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalProjects_ActionGroup.java new file mode 100644 index 00000000..448b8c70 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudActionsForPhysicalProjects_ActionGroup.java @@ -0,0 +1,30 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; +import com.intellij.openapi.actionSystem.ex.ActionManagerEx; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.extensions.PluginId; + +public class CloudActionsForPhysicalProjects_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudActionsForPhysicalProjects_ActionGroup"; + + public CloudActionsForPhysicalProjects_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("CloudActionsForPhysicalProjects", ID, plugin); + setIsInternal(false); + setPopup(false); + { + GeneratedActionGroup newAction = new CloudActionsForPhysicalProjectsCloudActions_ActionGroup(getApplicationPlugin()); + ActionManagerEx manager = ActionManagerEx.getInstanceEx(); + AnAction oldAction = manager.getAction(newAction.getId()); + if (oldAction == null) { + manager.registerAction(newAction.getId(), newAction, PluginId.getId("org.modelix.model.mpsplugin")); + oldAction = newAction; + } + CloudActionsForPhysicalProjects_ActionGroup.this.addAction(oldAction); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudBindingGroup_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudBindingGroup_ActionGroup.java new file mode 100644 index 00000000..24c356b3 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudBindingGroup_ActionGroup.java @@ -0,0 +1,18 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; + +public class CloudBindingGroup_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudBindingGroup_ActionGroup"; + + public CloudBindingGroup_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("CloudBindingGroup", ID, plugin); + setIsInternal(false); + setPopup(false); + CloudBindingGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.Unbind_Action"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudBranchGroup_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudBranchGroup_ActionGroup.java new file mode 100644 index 00000000..c8a904f7 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudBranchGroup_ActionGroup.java @@ -0,0 +1,20 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; + +public class CloudBranchGroup_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudBranchGroup_ActionGroup"; + + public CloudBranchGroup_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("CloudBranchGroup", ID, plugin); + setIsInternal(false); + setPopup(false); + CloudBranchGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.AddBranch_Action"); + CloudBranchGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.SwitchBranch_Action"); + CloudBranchGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.LoadHistoryForBranch_Action"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudHistoryTool_Tool.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudHistoryTool_Tool.java new file mode 100644 index 00000000..bdd3f220 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudHistoryTool_Tool.java @@ -0,0 +1,35 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.tool.GeneratedTool; +import javax.swing.Icon; +import org.modelix.model.mpsplugin.history.HistoryView; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindowAnchor; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.lazy.RepositoryId; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import org.modelix.model.lazy.CLVersion; +import javax.swing.JComponent; + +public class CloudHistoryTool_Tool extends GeneratedTool { + private static final Icon ICON = IconContainer.ICON_a0_0; + private HistoryView component; + public CloudHistoryTool_Tool(Project project) { + super(project, "Cloud History", null, ICON, ToolWindowAnchor.BOTTOM, false); + } + public void init(Project project) { + super.init(project); + } + public void load(ModelServerConnection modelServer, RepositoryId repositoryId, _FunctionTypes._return_P0_E0 headVersion) { + ((HistoryView) CloudHistoryTool_Tool.this.getComponent()).loadHistory(modelServer, repositoryId, headVersion); + CloudHistoryTool_Tool.this.openTool(true); + } + public JComponent getComponent() { + if (CloudHistoryTool_Tool.this.component == null) { + CloudHistoryTool_Tool.this.component = new HistoryView(); + } + return CloudHistoryTool_Tool.this.component; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroupAddChild_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroupAddChild_ActionGroup.java new file mode 100644 index 00000000..5de731b6 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroupAddChild_ActionGroup.java @@ -0,0 +1,120 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import java.util.Set; +import com.intellij.openapi.util.Pair; +import jetbrains.mps.workbench.ActionPlace; +import org.jetbrains.mps.util.Condition; +import jetbrains.mps.workbench.action.BaseAction; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; +import com.intellij.openapi.actionSystem.AnActionEvent; +import jetbrains.mps.project.MPSProject; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.api.INode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.api.IConcept; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.modelix.model.mpsplugin.ModelixNotifications; +import org.jetbrains.mps.openapi.language.SLanguage; +import jetbrains.mps.smodel.language.LanguageRegistry; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.internal.collections.runtime.CollectionSequence; +import java.util.Objects; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SConceptOperations; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.annotations.Nullable; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class CloudNodeGroupAddChild_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudNodeGroupAddChild_ActionGroup"; + private final Set>> myPlaces = SetSequence.fromSet(new HashSet>>()); + + public CloudNodeGroupAddChild_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("Add Child Node", ID, plugin); + setIsInternal(false); + setPopup(true); + } + public void doUpdate(AnActionEvent event) { + removeAll(); + MPSProject project = event.getData(MPSCommonDataKeys.MPS_PROJECT); + CloudNodeTreeNode treeNode = as_pvys46_a0a2a4(event.getData(MPSCommonDataKeys.TREE_NODE), CloudNodeTreeNode.class); + if (treeNode == null) { + return; + } + INode node = treeNode.getNode(); + if (!(node instanceof PNodeAdapter)) { + return; + } + PNodeAdapter pnode = ((PNodeAdapter) node); + IConcept concept = pnode.getConcept(); + if (concept == null) { + return; + } + SAbstractConcept sconcept = SConceptAdapter.unwrap(concept); + if (sconcept == null) { + ModelixNotifications.notifyError("Unable to unwrap concept", "We were unable to unwrap concept " + concept.getLongName() + " (" + concept.getClass().getCanonicalName() + ")", project); + return; + } + + Iterable allLanguages_ = LanguageRegistry.getInstance(project.getRepository()).getAllLanguages(); + Set allLanguages = SetSequence.fromSetWithValues(new HashSet(), allLanguages_); + + for (SContainmentLink role : CollectionSequence.fromCollection(sconcept.getContainmentLinks())) { + if (Objects.equals(role, LINKS.smodelAttribute$KJ43)) { + continue; + } + Iterable subConcepts = SConceptOperations.getAllSubConcepts(role.getTargetConcept(), allLanguages); + subConcepts = Sequence.fromIterable(subConcepts).where(new IWhereFilter() { + public boolean accept(SAbstractConcept it) { + return !(it.isAbstract()); + } + }); + if (Objects.equals(role, LINKS.rootNodes$jxXY)) { + subConcepts = Sequence.fromIterable(subConcepts).ofType(SConcept.class).where(new IWhereFilter() { + public boolean accept(SConcept it) { + return it.isRootable(); + } + }).ofType(SAbstractConcept.class); + } + subConcepts = Sequence.fromIterable(subConcepts).sort(new ISelector() { + public String select(SAbstractConcept it) { + return it.getLanguage().getQualifiedName(); + } + }, true).alsoSort(new ISelector() { + public String select(SAbstractConcept it) { + return it.getName(); + } + }, true); + for (SAbstractConcept subconcept : Sequence.fromIterable(subConcepts)) { + CloudNodeGroupAddChild_ActionGroup.this.addParameterizedAction(new AddChildNode_Action(node, subconcept, role), node, subconcept, role); + } + } + for (Pair> p : this.myPlaces) { + this.addPlace(p.first, p.second); + } + } + public void addPlace(ActionPlace place, @Nullable Condition cond) { + SetSequence.fromSet(this.myPlaces).addElement(new Pair>(place, cond)); + } + public boolean isStrict() { + return false; + } + private static T as_pvys46_a0a2a4(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink smodelAttribute$KJ43 = MetaAdapterFactory.getContainmentLink(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x10802efe25aL, 0x47bf8397520e5942L, "smodelAttribute"); + /*package*/ static final SContainmentLink rootNodes$jxXY = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x69652614fd1c514L, "rootNodes"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroupSetProperty_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroupSetProperty_ActionGroup.java new file mode 100644 index 00000000..320de8d1 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroupSetProperty_ActionGroup.java @@ -0,0 +1,77 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import java.util.Set; +import com.intellij.openapi.util.Pair; +import jetbrains.mps.workbench.ActionPlace; +import org.jetbrains.mps.util.Condition; +import jetbrains.mps.workbench.action.BaseAction; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; +import com.intellij.openapi.actionSystem.AnActionEvent; +import jetbrains.mps.project.MPSProject; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.api.INode; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.api.IConcept; +import org.jetbrains.mps.openapi.language.SAbstractConcept; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.jetbrains.annotations.Nullable; + +public class CloudNodeGroupSetProperty_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudNodeGroupSetProperty_ActionGroup"; + private final Set>> myPlaces = SetSequence.fromSet(new HashSet>>()); + + public CloudNodeGroupSetProperty_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("Set Property", ID, plugin); + setIsInternal(false); + setPopup(true); + } + public void doUpdate(AnActionEvent event) { + removeAll(); + MPSProject project = event.getData(MPSCommonDataKeys.MPS_PROJECT); + CloudNodeTreeNode treeNode = as_shasbg_a0a2a4(event.getData(MPSCommonDataKeys.TREE_NODE), CloudNodeTreeNode.class); + if (treeNode == null) { + return; + } + INode node = treeNode.getNode(); + if (!(node instanceof PNodeAdapter)) { + return; + } + PNodeAdapter pnode = ((PNodeAdapter) node); + IConcept concept = pnode.getConcept(); + if (concept == null) { + return; + } + SAbstractConcept sconcept = SConceptAdapter.unwrap(concept); + + Iterable properties = sconcept.getProperties(); + for (SProperty role : Sequence.fromIterable(properties).sort(new ISelector() { + public String select(SProperty it) { + return it.getName(); + } + }, true)) { + CloudNodeGroupSetProperty_ActionGroup.this.addParameterizedAction(new SetProperty_Action(node, role), node, role); + } + for (Pair> p : this.myPlaces) { + this.addPlace(p.first, p.second); + } + } + public void addPlace(ActionPlace place, @Nullable Condition cond) { + SetSequence.fromSet(this.myPlaces).addElement(new Pair>(place, cond)); + } + public boolean isStrict() { + return false; + } + private static T as_shasbg_a0a2a4(Object o, Class type) { + return (type.isInstance(o) ? (T) o : null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroup_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroup_ActionGroup.java new file mode 100644 index 00000000..37a98eb8 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudNodeGroup_ActionGroup.java @@ -0,0 +1,54 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; +import com.intellij.openapi.actionSystem.ex.ActionManagerEx; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.extensions.PluginId; + +public class CloudNodeGroup_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudNodeGroup_ActionGroup"; + + public CloudNodeGroup_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("CloudNodeGroup", ID, plugin); + setIsInternal(false); + setPopup(false); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.AddProjectNode_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.AddModuleNode_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.AddModelNode_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.AddProjectBinding_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.StoreAllModules_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.DeleteProject_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.DeleteModule_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.AddTransientModuleBinding_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.RemoveTransientModuleBinding_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.CheckoutModule_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.CheckoutAndSyncModule_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.NavigateToMpsNode_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.ShowProperties_Action"); + CloudNodeGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.ShowReferences_Action"); + { + GeneratedActionGroup newAction = new CloudNodeGroupAddChild_ActionGroup(getApplicationPlugin()); + ActionManagerEx manager = ActionManagerEx.getInstanceEx(); + AnAction oldAction = manager.getAction(newAction.getId()); + if (oldAction == null) { + manager.registerAction(newAction.getId(), newAction, PluginId.getId("org.modelix.model.mpsplugin")); + oldAction = newAction; + } + CloudNodeGroup_ActionGroup.this.addAction(oldAction); + } + { + GeneratedActionGroup newAction = new CloudNodeGroupSetProperty_ActionGroup(getApplicationPlugin()); + ActionManagerEx manager = ActionManagerEx.getInstanceEx(); + AnAction oldAction = manager.getAction(newAction.getId()); + if (oldAction == null) { + manager.registerAction(newAction.getId(), newAction, PluginId.getId("org.modelix.model.mpsplugin")); + oldAction = newAction; + } + CloudNodeGroup_ActionGroup.this.addAction(oldAction); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudResourcesConfigurationComponent.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudResourcesConfigurationComponent.java new file mode 100644 index 00000000..1f4cf69d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudResourcesConfigurationComponent.java @@ -0,0 +1,89 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import com.intellij.openapi.components.Service; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.components.RoamingType; +import com.intellij.openapi.components.PersistentStateComponent; +import org.jetbrains.annotations.NotNull; +import java.util.Set; +import java.util.LinkedHashSet; +import java.util.Objects; + +/** + * This component handles the storage of the cloud configuration. + * For information about component persistence refer to https://jetbrains.org/intellij/sdk/docs/basics/persisting_state_of_components.html + */ +@Service +@com.intellij.openapi.components.State(name = "CloudResources", storages = @Storage(file = "cloudResources.xml", value = "cloudResources.xml", roamingType = RoamingType.DISABLED) +, reloadable = true) +public final class CloudResourcesConfigurationComponent implements PersistentStateComponent { + + /*package*/ static class State { + @NotNull + public Set modelServers; + @NotNull + public Set transientProjects; + @NotNull + public Set transientModules; + @NotNull + public Set mappedModules; + + /*package*/ State() { + modelServers = new LinkedHashSet(); + transientModules = new LinkedHashSet(); + transientProjects = new LinkedHashSet(); + mappedModules = new LinkedHashSet(); + } + + @Override + public int hashCode() { + int hc = 1; + hc += 3 * modelServers.hashCode(); + hc += 7 * transientProjects.hashCode(); + hc += 11 * transientModules.hashCode(); + hc += 13 * mappedModules.hashCode(); + return hc; + } + @Override + public boolean equals(Object obj) { + if (obj instanceof State) { + State other = ((State) obj); + if (!(Objects.equals(transientProjects, other.transientProjects))) { + return false; + } + if (!(Objects.equals(modelServers, other.modelServers))) { + return false; + } + if (!(Objects.equals(transientModules, other.transientModules))) { + return false; + } + if (!(Objects.equals(mappedModules, other.mappedModules))) { + return false; + } + return true; + } else { + return false; + } + } + @Override + public String toString() { + return "State(cloudRepositories: " + modelServers + ", transientProjects: " + transientProjects + ", transientModules: " + transientModules + ", mappedModules: " + mappedModules + ")"; + } + } + public CloudResourcesConfigurationComponent() { + } + @NotNull + private State state = new State(); + + @Override + @NotNull + public State getState() { + return state; + } + @Override + public void loadState(@NotNull State state) { + this.state = state; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudRootGroup_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudRootGroup_ActionGroup.java new file mode 100644 index 00000000..13e1f3c8 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudRootGroup_ActionGroup.java @@ -0,0 +1,18 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; + +public class CloudRootGroup_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.CloudRootGroup_ActionGroup"; + + public CloudRootGroup_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("CloudRootGroup", ID, plugin); + setIsInternal(false); + setPopup(false); + CloudRootGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.AddModelServer_Action"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudTool_Tool.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudTool_Tool.java new file mode 100644 index 00000000..70be4a36 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CloudTool_Tool.java @@ -0,0 +1,28 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.tool.GeneratedTool; +import javax.swing.Icon; +import org.modelix.model.mpsplugin.history.CloudView; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindowAnchor; +import javax.swing.JComponent; + +public class CloudTool_Tool extends GeneratedTool { + private static final Icon ICON = IconContainer.ICON_a0; + private CloudView component; + public CloudTool_Tool(Project project) { + super(project, "Cloud", null, ICON, ToolWindowAnchor.BOTTOM, false); + } + public void init(Project project) { + super.init(project); + CloudTool_Tool.this.makeAvailableLater(); + } + public JComponent getComponent() { + if (CloudTool_Tool.this.component == null) { + CloudTool_Tool.this.component = new CloudView(); + } + return CloudTool_Tool.this.component; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyAndSyncPhysicalModuleOnCloud_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyAndSyncPhysicalModuleOnCloud_Action.java new file mode 100644 index 00000000..825e3e36 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyAndSyncPhysicalModuleOnCloud_Action.java @@ -0,0 +1,91 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import org.modelix.model.mpsplugin.CloudRepository; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.ModelCloudImportUtils; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import org.jetbrains.mps.openapi.module.SModule; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.progress.ProgressIndicator; +import jetbrains.mps.progress.ProgressMonitorAdapter; + +public class CopyAndSyncPhysicalModuleOnCloud_Action extends BaseAction { + private static final Icon ICON = null; + + private CloudRepository treeInRepository; + public CopyAndSyncPhysicalModuleOnCloud_Action(CloudRepository treeInRepository_par) { + super("Copy on Cloud & Sync", "", ICON); + this.treeInRepository = treeInRepository_par; + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + boolean connected = CopyAndSyncPhysicalModuleOnCloud_Action.this.treeInRepository.isConnected(); + event.getPresentation().setText("Copy on Cloud and Sync -> " + CopyAndSyncPhysicalModuleOnCloud_Action.this.treeInRepository.presentation()); + try { + return connected && !(ModelCloudImportUtils.containsModule(CopyAndSyncPhysicalModuleOnCloud_Action.this.treeInRepository, event.getData(MPSCommonDataKeys.MODULE))); + } catch (RuntimeException e) { + // This could happen because of repositories in invalid state. In this case let's ignore those repositories without preventing usage of other repositories + return false; + } + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + SModule p = event.getData(MPSCommonDataKeys.MODULE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + new Task.Modal(event.getData(CommonDataKeys.PROJECT), "Copy on Cloud", false) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + ModelCloudImportUtils.copyAndSyncInModelixAsIndependentModule(CopyAndSyncPhysicalModuleOnCloud_Action.this.treeInRepository, event.getData(MPSCommonDataKeys.MODULE), event.getData(CommonDataKeys.PROJECT), new ProgressMonitorAdapter(indicator)); + } + }.queue(); + + } + @NotNull + public String getActionId() { + StringBuilder res = new StringBuilder(); + res.append(super.getActionId()); + res.append("#"); + res.append(treeInRepository_State((CloudRepository) this.treeInRepository)); + res.append("!"); + return res.toString(); + } + public static String treeInRepository_State(CloudRepository object) { + return object.presentation(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyAndSyncPhysicalProjectOnCloud_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyAndSyncPhysicalProjectOnCloud_Action.java new file mode 100644 index 00000000..0776990c --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyAndSyncPhysicalProjectOnCloud_Action.java @@ -0,0 +1,87 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import org.modelix.model.mpsplugin.CloudRepository; +import org.jetbrains.mps.openapi.model.SNode; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import jetbrains.mps.lang.core.behavior.INamedConcept__BehaviorDescriptor; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.project.MPSProject; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.ModelCloudImportUtils; + +public class CopyAndSyncPhysicalProjectOnCloud_Action extends BaseAction { + private static final Icon ICON = null; + + private CloudRepository treeInRepository; + private SNode cloudProject; + public CopyAndSyncPhysicalProjectOnCloud_Action(CloudRepository treeInRepository_par, SNode cloudProject_par) { + super("Copy on Cloud & Sync", "", ICON); + this.treeInRepository = treeInRepository_par; + this.cloudProject = cloudProject_par; + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + if (CopyAndSyncPhysicalProjectOnCloud_Action.this.cloudProject == null) { + event.getPresentation().setText("Copy on Cloud and Sync -> " + CopyAndSyncPhysicalProjectOnCloud_Action.this.treeInRepository.presentation() + " as new project"); + + } else { + CopyAndSyncPhysicalProjectOnCloud_Action.this.treeInRepository.runRead(new Runnable() { + public void run() { + event.getPresentation().setText("Sync to Cloud Repo " + CopyAndSyncPhysicalProjectOnCloud_Action.this.treeInRepository.presentation() + " to project " + INamedConcept__BehaviorDescriptor.getFqName_idhEwIO9y.invoke(CopyAndSyncPhysicalProjectOnCloud_Action.this.cloudProject)); + } + }); + } + // TODO verify it is not already stored + return CopyAndSyncPhysicalProjectOnCloud_Action.this.treeInRepository.isConnected(); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + MPSProject p = event.getData(MPSCommonDataKeys.MPS_PROJECT); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + ModelCloudImportUtils.copyAndSyncInModelixAsEntireProject(CopyAndSyncPhysicalProjectOnCloud_Action.this.treeInRepository, event.getData(MPSCommonDataKeys.MPS_PROJECT), CopyAndSyncPhysicalProjectOnCloud_Action.this.cloudProject); + } + @NotNull + public String getActionId() { + StringBuilder res = new StringBuilder(); + res.append(super.getActionId()); + res.append("#"); + res.append(treeInRepository_State((CloudRepository) this.treeInRepository)); + res.append("!"); + res.append(cloudProject_State((SNode) this.cloudProject)); + res.append("!"); + return res.toString(); + } + public static String treeInRepository_State(CloudRepository object) { + return object.presentation(); + } + public static String cloudProject_State(SNode object) { + return (String) INamedConcept__BehaviorDescriptor.getFqName_idhEwIO9y.invoke(object); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyPhysicalModuleOnCloud_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyPhysicalModuleOnCloud_Action.java new file mode 100644 index 00000000..3119857a --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/CopyPhysicalModuleOnCloud_Action.java @@ -0,0 +1,91 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import org.modelix.model.mpsplugin.CloudRepository; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.ModelCloudImportUtils; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import org.jetbrains.mps.openapi.module.SModule; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.progress.ProgressIndicator; +import jetbrains.mps.progress.ProgressMonitorAdapter; + +public class CopyPhysicalModuleOnCloud_Action extends BaseAction { + private static final Icon ICON = null; + + private CloudRepository treeInRepository; + public CopyPhysicalModuleOnCloud_Action(CloudRepository treeInRepository_par) { + super("Copy on Cloud", "", ICON); + this.treeInRepository = treeInRepository_par; + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + boolean connected = CopyPhysicalModuleOnCloud_Action.this.treeInRepository.isConnected(); + event.getPresentation().setText("Copy on Cloud -> " + CopyPhysicalModuleOnCloud_Action.this.treeInRepository.presentation()); + try { + return connected && !(ModelCloudImportUtils.containsModule(CopyPhysicalModuleOnCloud_Action.this.treeInRepository, event.getData(MPSCommonDataKeys.MODULE))); + } catch (RuntimeException e) { + // This could happen because of repositories in invalid state. In this case let's ignore those repositories without preventing usage of other repositories + return false; + } + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + SModule p = event.getData(MPSCommonDataKeys.MODULE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + new Task.Modal(event.getData(CommonDataKeys.PROJECT), "Copy on Cloud", false) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + ModelCloudImportUtils.copyInModelixAsIndependentModule(CopyPhysicalModuleOnCloud_Action.this.treeInRepository, event.getData(MPSCommonDataKeys.MODULE), event.getData(CommonDataKeys.PROJECT), new ProgressMonitorAdapter(indicator)); + } + }.queue(); + + } + @NotNull + public String getActionId() { + StringBuilder res = new StringBuilder(); + res.append(super.getActionId()); + res.append("#"); + res.append(treeInRepository_State((CloudRepository) this.treeInRepository)); + res.append("!"); + return res.toString(); + } + public static String treeInRepository_State(CloudRepository object) { + return object.presentation(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/DeleteModule_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/DeleteModule_Action.java new file mode 100644 index 00000000..4577972e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/DeleteModule_Action.java @@ -0,0 +1,64 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.project.MPSProject; +import javax.swing.tree.TreeNode; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.history.TreeNodeAccess; + +public class DeleteModule_Action extends BaseAction { + private static final Icon ICON = null; + + public DeleteModule_Action() { + super("Delete Module", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isModuleNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + MPSProject p = event.getData(MPSCommonDataKeys.MPS_PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + int dialogResult = Messages.showOkCancelDialog(event.getData(MPSCommonDataKeys.MPS_PROJECT).getProject(), "Are you sure you want to delete module '" + TreeNodeAccess.getName(event.getData(MPSCommonDataKeys.TREE_NODE)) + "' ?", "Delete Module", null); + if (dialogResult != Messages.OK) { + return; + } + TreeNodeAccess.delete(event.getData(MPSCommonDataKeys.TREE_NODE)); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/DeleteProject_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/DeleteProject_Action.java new file mode 100644 index 00000000..5d6f59af --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/DeleteProject_Action.java @@ -0,0 +1,64 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.project.MPSProject; +import javax.swing.tree.TreeNode; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.history.TreeNodeAccess; + +public class DeleteProject_Action extends BaseAction { + private static final Icon ICON = null; + + public DeleteProject_Action() { + super("Delete Project", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isProjectNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + MPSProject p = event.getData(MPSCommonDataKeys.MPS_PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + int dialogResult = Messages.showOkCancelDialog(event.getData(MPSCommonDataKeys.MPS_PROJECT).getProject(), "Are you sure you want to delete project '" + TreeNodeAccess.getName(event.getData(MPSCommonDataKeys.TREE_NODE)) + "' ?", "Delete Project", null); + if (dialogResult != Messages.OK) { + return; + } + TreeNodeAccess.delete(event.getData(MPSCommonDataKeys.TREE_NODE)); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/EModelixExecutionMode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/EModelixExecutionMode.java new file mode 100644 index 00000000..7755f753 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/EModelixExecutionMode.java @@ -0,0 +1,13 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + + +public enum EModelixExecutionMode { + DEFAULT(), + INTEGRATION_TESTS(), + MODEL_EXPORT(), + MODEL_IMPORT(), + CLUSTER(), + PROJECTOR() +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/GetCloudRepositorySize_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/GetCloudRepositorySize_Action.java new file mode 100644 index 00000000..af40853b --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/GetCloudRepositorySize_Action.java @@ -0,0 +1,71 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.modelix.model.client.ActiveBranch; +import org.modelix.model.api.IBranch; +import kotlin.jvm.functions.Function0; +import org.modelix.model.api.ITree; +import org.modelix.model.lazy.ITreeWrapperKt; +import org.modelix.model.lazy.CLTree; +import com.intellij.openapi.ui.Messages; + +public class GetCloudRepositorySize_Action extends BaseAction { + private static final Icon ICON = null; + + public GetCloudRepositorySize_Action() { + super("Get Number of Nodes", "", ICON); + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + RepositoryTreeNode treeNode = (RepositoryTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + ActiveBranch activeBranch = treeNode.getModelServer().getActiveBranch(treeNode.getRepositoryId()); + final IBranch branch = activeBranch.getBranch(); + long size = branch.computeRead(new Function0() { + public Long invoke() { + ITree tree = ITreeWrapperKt.unwrap(branch.getTransaction().getTree()); + if (tree instanceof CLTree) { + return ((CLTree) tree).getSize(); + } + return 0L; + } + }); + Messages.showInfoMessage(event.getData(CommonDataKeys.PROJECT), "Size is " + size, "Size of Repository"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/IconContainer.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/IconContainer.java new file mode 100644 index 00000000..01b61961 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/IconContainer.java @@ -0,0 +1,11 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import javax.swing.Icon; +import jetbrains.mps.ide.icons.IconLoadingUtil; + +public class IconContainer { + protected static Icon ICON_a0 = IconLoadingUtil.loadIcon("TextIcon_1.png", IconContainer.class); + protected static Icon ICON_a0_0 = IconLoadingUtil.loadIcon("TextIcon_13262.png", IconContainer.class); +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/LoadHistoryForBranch_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/LoadHistoryForBranch_Action.java new file mode 100644 index 00000000..46edd2e1 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/LoadHistoryForBranch_Action.java @@ -0,0 +1,96 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.mpsplugin.history.CloudBranchTreeNode; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.modelix.model.api.IBranch; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.client.IModelClient; +import org.modelix.model.mpsplugin.SharedExecutors; +import org.modelix.model.lazy.CLVersion; +import javax.swing.SwingUtilities; +import jetbrains.mps.plugins.projectplugins.ProjectPluginManager; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class LoadHistoryForBranch_Action extends BaseAction { + private static final Icon ICON = null; + + public LoadHistoryForBranch_Action() { + super("Show History", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + final CloudBranchTreeNode branchTNode = (CloudBranchTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + RepositoryTreeNode treeTNode = branchTNode.getAncestor(RepositoryTreeNode.class); + IBranch infoBranch = treeTNode.getModelServer().getInfoBranch(); + String branchName = new PArea(infoBranch).executeRead(new Function0() { + public String invoke() { + return SPropertyOperations.getString(branchTNode.getBranchInfo(), PROPS.name$MnvL); + } + }); + final RepositoryId repositoryId = treeTNode.getRepositoryId(); + final String branchKey = repositoryId.getBranchKey(branchName); + final ModelServerConnection modelServer = treeTNode.getModelServer(); + final IModelClient client = modelServer.getClient(); + SharedExecutors.FIXED.execute(new Runnable() { + public void run() { + String versionHash = client.get(branchKey); + final CLVersion version = CLVersion.Companion.loadFromHash(versionHash, client.getStoreCache()); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + event.getData(CommonDataKeys.PROJECT).getComponent(ProjectPluginManager.class).getTool(CloudHistoryTool_Tool.class).load(modelServer, repositoryId, new _FunctionTypes._return_P0_E0() { + public CLVersion invoke() { + return version; + } + }); + } + }); + } + }); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/LoadHistoryForRepository_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/LoadHistoryForRepository_Action.java new file mode 100644 index 00000000..e74a419e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/LoadHistoryForRepository_Action.java @@ -0,0 +1,62 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.modelix.model.client.ActiveBranch; +import jetbrains.mps.plugins.projectplugins.ProjectPluginManager; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import org.modelix.model.lazy.CLVersion; + +public class LoadHistoryForRepository_Action extends BaseAction { + private static final Icon ICON = null; + + public LoadHistoryForRepository_Action() { + super("Show History", "", ICON); + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + RepositoryTreeNode treeNode = (RepositoryTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + final ActiveBranch activeBranch = treeNode.getModelServer().getActiveBranch(treeNode.getRepositoryId()); + event.getData(CommonDataKeys.PROJECT).getComponent(ProjectPluginManager.class).getTool(CloudHistoryTool_Tool.class).load(treeNode.getModelServer(), treeNode.getRepositoryId(), new _FunctionTypes._return_P0_E0() { + public CLVersion invoke() { + return activeBranch.getVersion(); + } + }); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/MetaMetaModelMappings.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/MetaMetaModelMappings.java new file mode 100644 index 00000000..325909bf --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/MetaMetaModelMappings.java @@ -0,0 +1,49 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.model.mpsadapters.mps.BootstrapConceptMappings; +import org.modelix.model.metameta.MetaMetaLanguage; +import org.apache.log4j.Level; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class MetaMetaModelMappings { + private static final Logger LOG = LogManager.getLogger(MetaMetaModelMappings.class); + public static void register() { + try { + BootstrapConceptMappings.INSTANCE.register(MetaMetaLanguage.INSTANCE.getConcept_Language(), CONCEPTS.Language$L1); + BootstrapConceptMappings.INSTANCE.register(MetaMetaLanguage.INSTANCE.getConcept_Concept(), CONCEPTS.Concept$Lw); + BootstrapConceptMappings.INSTANCE.register(MetaMetaLanguage.INSTANCE.getConcept_Property(), CONCEPTS.Property$LZ); + BootstrapConceptMappings.INSTANCE.register(MetaMetaLanguage.INSTANCE.getConcept_ChildLink(), CONCEPTS.ContainmentLink$X8); + BootstrapConceptMappings.INSTANCE.register(MetaMetaLanguage.INSTANCE.getConcept_ReferenceLink(), CONCEPTS.ReferenceLink$WD); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + public static void unregister() { + try { + BootstrapConceptMappings.INSTANCE.unregister(MetaMetaLanguage.INSTANCE.getConcept_Language(), CONCEPTS.Language$L1); + BootstrapConceptMappings.INSTANCE.unregister(MetaMetaLanguage.INSTANCE.getConcept_Concept(), CONCEPTS.Concept$Lw); + BootstrapConceptMappings.INSTANCE.unregister(MetaMetaLanguage.INSTANCE.getConcept_Property(), CONCEPTS.Property$LZ); + BootstrapConceptMappings.INSTANCE.unregister(MetaMetaLanguage.INSTANCE.getConcept_ChildLink(), CONCEPTS.ContainmentLink$X8); + BootstrapConceptMappings.INSTANCE.unregister(MetaMetaLanguage.INSTANCE.getConcept_ReferenceLink(), CONCEPTS.ReferenceLink$WD); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Language$L1 = MetaAdapterFactory.getConcept(0xbffdf1230d7b471bL, 0xa52bfa3d3a024664L, 0x100c617ef3bce7efL, "org.modelix.model.metametamodel.structure.Language"); + /*package*/ static final SConcept Concept$Lw = MetaAdapterFactory.getConcept(0xbffdf1230d7b471bL, 0xa52bfa3d3a024664L, 0x100c617ef3bce7f0L, "org.modelix.model.metametamodel.structure.Concept"); + /*package*/ static final SConcept Property$LZ = MetaAdapterFactory.getConcept(0xbffdf1230d7b471bL, 0xa52bfa3d3a024664L, 0x100c617ef3bce7f1L, "org.modelix.model.metametamodel.structure.Property"); + /*package*/ static final SConcept ContainmentLink$X8 = MetaAdapterFactory.getConcept(0xbffdf1230d7b471bL, 0xa52bfa3d3a024664L, 0x100c617ef3bce7f3L, "org.modelix.model.metametamodel.structure.ContainmentLink"); + /*package*/ static final SConcept ReferenceLink$WD = MetaAdapterFactory.getConcept(0xbffdf1230d7b471bL, 0xa52bfa3d3a024664L, 0x100c617ef3bce7f2L, "org.modelix.model.metametamodel.structure.ReferenceLink"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelImportExport.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelImportExport.java new file mode 100644 index 00000000..9b8c7eef --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelImportExport.java @@ -0,0 +1,367 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.common.PropertyOrEnv; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import java.io.PrintWriter; +import java.net.Socket; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.StringWriter; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.mpsplugin.ModelServerConnections; +import java.util.function.Consumer; +import com.intellij.openapi.application.ApplicationManager; +import org.modelix.model.mpsplugin.ModelCloudExporter; +import jetbrains.mps.project.Project; +import java.util.List; +import org.jetbrains.mps.openapi.module.SModule; +import java.util.Objects; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import jetbrains.mps.project.StandaloneMPSProject; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IterableUtils; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; +import jetbrains.mps.messages.IMessage; +import org.apache.log4j.Level; +import com.intellij.openapi.project.ProjectManager; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.client.ActiveBranch; +import kotlin.jvm.functions.Function1; +import org.modelix.model.api.IWriteTransaction; +import org.modelix.model.api.ITree; +import org.modelix.model.api.IConcept; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.modelix.model.mpsplugin.ProjectBinding; +import jetbrains.mps.project.MPSProject; +import org.modelix.model.mpsplugin.SyncDirection; +import org.modelix.model.mpsplugin.Binding; +import org.modelix.model.client.IModelClient; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import org.jetbrains.mps.openapi.language.SConcept; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class ModelImportExport { + private static final Logger LOG = LogManager.getLogger(ModelImportExport.class); + public void cloud2mps() { + final String exportPath = PropertyOrEnv.get(ModelixExportConfiguration.PATH); + System.out.println("Modelix Application Plugin - export path: " + exportPath); + if ((exportPath == null || exportPath.length() == 0)) { + System.err.println(ModelixExportConfiguration.PATH + " not provided"); + System.exit(1); + } + try { + System.out.println("Modelix Application Plugin - Starting model export ..."); + System.setProperty(ModelixExportConfiguration.STARTED, "true"); + final String modelServerURL = PropertyOrEnv.get(ModelixExportConfiguration.SERVER_URL); + + System.out.println("Modelix Application Plugin - consider gradle task connection"); + String socketPortStr = PropertyOrEnv.get(ModelixExportConfiguration.GRADLE_PLUGIN_SOCKET_PORT); + final Wrappers._T gradleTaskOut = new Wrappers._T(); + if (socketPortStr != null && !((socketPortStr == null || socketPortStr.length() == 0))) { + System.out.println("Modelix Application Plugin - connecting to gradle task on port " + socketPortStr); + int gradleTaskPort = Integer.parseInt(socketPortStr); + Socket gradleTaskClient = new Socket("127.0.0.1", gradleTaskPort); + gradleTaskOut.value = new PrintWriter(gradleTaskClient.getOutputStream(), true); + BufferedReader gradleTaskIn = new BufferedReader(new InputStreamReader(gradleTaskClient.getInputStream())); + } else { + System.out.println("Modelix Application Plugin - connecting to gradle task not requested"); + StringWriter sw = new StringWriter(); + gradleTaskOut.value = new PrintWriter(sw, true); + } + System.out.println("Modelix Application Plugin - gradle task considered"); + + ModelServerConnection modelServerConnection = ModelServerConnections.getInstance().ensureModelServerIsPresent(modelServerURL); + System.out.println("Modelix Application Plugin - Waiting for Model Server Connection"); + modelServerConnection.whenConnected(new Consumer() { + @Override + public void accept(ModelServerConnection connection) { + System.out.println("Modelix Application Plugin - Connected, starting ModelCloudExporter"); + ApplicationManager.getApplication().invokeLaterOnWriteThread(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + try { + final ModelCloudExporter modelCloudExporter = new ModelCloudExporter(modelServerURL, PropertyOrEnv.get(ModelixExportConfiguration.REPOSITORY_ID), PropertyOrEnv.get(ModelixExportConfiguration.BRANCH_NAME)).setCheckoutMode(); + Consumer stuffToDoOnceWeGetAProject = new Consumer() { + @Override + public void accept(final Project mpsProject) { + System.out.println("Modelix Application Plugin - Got the project: " + mpsProject); + + final Runnable runExport = new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + System.out.println("========================================================"); + System.out.println("Modelix Application Plugin - Running the actual exporter"); + System.out.println("========================================================"); + + mpsProject.getRepository().getModelAccess().executeCommand(new Runnable() { + public void run() { + try { + modelCloudExporter.setCheckoutMode().export(exportPath, mpsProject); + // Application.exit does not let us set a proper exit code, therefore we communicate + // we failed or managed to export through strings... + System.out.println("DOWNLOAD TASK WRITING " + "\n"); + gradleTaskOut.value.println(""); + } catch (Throwable t) { + t.printStackTrace(); + System.out.println("CHECKOUT FAILED"); + // Application.exit does not let us set a proper exit code, therefore we communicate + // we failed or managed to export through strings... + System.out.println("DOWNLOAD TASK WRITING " + "\n"); + gradleTaskOut.value.println(""); + } + } + }); + System.setProperty(ModelixExportConfiguration.DONE, "true"); + System.out.println("Starting shut down of Application"); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().exit(true, true, false); + } + }); + } + }); + } + }; + final String make = PropertyOrEnv.get(ModelixExportConfiguration.MAKE); + if (make == null) { + System.out.println("Modelix Application Plugin - No need to run make"); + runExport.run(); + } else { + System.out.println("Modelix Application Plugin - Running make before export"); + List modulesToBuild = null; + if (Objects.equals(make, "all")) { + modulesToBuild = ListSequence.fromListWithValues(new ArrayList(), (Iterable) mpsProject.getProjectModules()); + } else { + modulesToBuild = ListSequence.fromList(ListSequence.fromListWithValues(new ArrayList(), (Iterable) mpsProject.getProjectModules())).where(new IWhereFilter() { + public boolean accept(SModule it) { + final String virtualFolder = ((StandaloneMPSProject) mpsProject).getFolderFor(it); + System.out.println("Modelix Application Plugin - Considering module: " + it.getModuleName() + " virtual folder: " + virtualFolder + ", make is currently: " + make); + return Sequence.fromIterable(Sequence.fromArray(make.split(","))).any(new IWhereFilter() { + public boolean accept(String it) { + return Objects.equals(virtualFolder, it); + } + }); + } + }).toListSequence(); + } + System.out.println("Modelix Application Plugin - Modules to be built: " + IterableUtils.join(ListSequence.fromList(modulesToBuild).select(new ISelector() { + public String select(SModule it) { + return it.getModuleName(); + } + }), ", ")); + new ProjectMakeRunner().execute(mpsProject, false, modulesToBuild, new Consumer>>() { + @Override + public void accept(Tuples._2> res) { + System.out.println("========================================================"); + System.out.println("Modelix Application Plugin - Make completed successfully"); + System.out.println("========================================================"); + + if (LOG.isDebugEnabled()) { + LOG.debug("Make messages:"); + } + for (IMessage message : ListSequence.fromList(res._1())) { + if (LOG.isDebugEnabled()) { + LOG.debug(" " + message.getKind() + " " + message.getText()); + } + } + if (LOG.isInfoEnabled()) { + LOG.info("Make Project Success: " + res._0()); + } + + System.out.println("========================================================"); + System.out.println("Modelix Application Plugin - Make completed successfully"); + System.out.println("========================================================"); + + runExport.run(); + } + }, new Consumer>>() { + @Override + public void accept(Tuples._2> res) { + System.out.println("========================================"); + System.out.println("Modelix Application Plugin - Make failed"); + System.out.println(" make message should follow:"); + System.out.println("========================================"); + + if (LOG.isDebugEnabled()) { + LOG.debug("Make messages:"); + } + for (IMessage message : ListSequence.fromList(res._1())) { + if (LOG.isInfoEnabled()) { + LOG.info(" " + message.getKind() + " " + message.getText()); + } + System.out.println(" " + message.getKind() + " " + message.getText()); + } + if (LOG.isEnabledFor(Level.WARN)) { + LOG.warn("Make Project Failure: " + res._0()); + } + + System.out.println("========================================"); + + // We try to export anyway + runExport.run(); + } + }); + } + } + }; + ProjectManagerExtensions.withTheOnlyProject(ProjectManager.getInstance(), stuffToDoOnceWeGetAProject); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Modelix Application Plugin Failure", ex); + } + // Application.exit does not let us set a proper exit code, therefore we communicate + // we failed or managed to export through strings... + System.out.println(""); + ApplicationManager.getApplication().exit(true, true, false); + } + } + }); + } + }); + } + }); + } catch (Exception ex) { + ex.printStackTrace(); + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Modelix Application Plugin Failure", ex); + } + System.exit(1); + } + } + + public void mps2cloud() { + try { + System.out.println("Modelix Application Plugin - Starting model import ..."); + System.setProperty(ModelixImportConfiguration.STARTED, "true"); + String modelServerURL = PropertyOrEnv.get(ModelixImportConfiguration.SERVER_URL); + ModelServerConnection modelServerConnection = ModelServerConnections.getInstance().ensureModelServerIsPresent(modelServerURL); + System.out.println("Modelix Application Plugin - Waiting for Model Server Connection"); + modelServerConnection.whenConnected(new Consumer() { + public void accept(final ModelServerConnection connection) { + System.out.println("Modelix Application Plugin - Connected, starting model import"); + ApplicationManager.getApplication().invokeLaterOnWriteThread(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + try { + ProjectManagerExtensions.withTheOnlyProject(ProjectManager.getInstance(), new Consumer() { + public void accept(Project project) { + System.out.println("Project " + project.getName() + " opened"); + for (SModule module : ListSequence.fromList(project.getProjectModules())) { + System.out.println("Project module: " + module.getModuleName()); + } + RepositoryId repositoryId = new RepositoryId(PropertyOrEnv.get(ModelixImportConfiguration.REPOSITORY_ID)); + ActiveBranch activeBranch = connection.getActiveBranch(repositoryId); + activeBranch.switchBranch(PropertyOrEnv.getOrElse(ModelixImportConfiguration.BRANCH_NAME, RepositoryId.DEFAULT_BRANCH)); + + long projectNodeId = activeBranch.getBranch().computeWriteT(new Function1() { + public Long invoke(final IWriteTransaction t) { + Iterable allChildren = t.getAllChildren(ITree.ROOT_ID); + final IConcept projectConcept = SConceptAdapter.wrap(CONCEPTS.Project$An); + Long id = Sequence.fromIterable(allChildren).findFirst(new IWhereFilter() { + public boolean accept(Long it) { + return check_d5jcfl_a0a0a0a2a0a0a6a0a0a0a0a0a0a0a0a0a1a0a0f0a0c(t.getConcept(it), projectConcept); + } + }); + if (id == null) { + id = t.addNewChild(ITree.ROOT_ID, "projects", -1, projectConcept); + } + return id; + } + }); + + final ProjectBinding binding = new ProjectBinding((MPSProject) project, projectNodeId, SyncDirection.TO_CLOUD); + connection.addBinding(repositoryId, binding, new Runnable() { + public void run() { + waitForWriteToModelServer(binding, connection.getClient(), new Runnable() { + public void run() { + System.out.println(""); + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + ApplicationManager.getApplication().exit(true, true, false); + } + }); + } + }); + } + }); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Modelix Application Plugin Failure", ex); + } + // Application.exit does not let us set a proper exit code, therefore we communicate + // we failed or managed to export through strings... + System.out.println(""); + ApplicationManager.getApplication().exit(true, true, false); + } + } + }); + } + }); + } + }); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Modelix Application Plugin Failure", ex); + } + System.exit(1); + } + } + + private void waitForWriteToModelServer(final Binding binding, final IModelClient client, final Runnable whenDone) { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + public void run() { + try { + _FunctionTypes._return_P0_E0 condition = new _FunctionTypes._return_P0_E0() { + public Boolean invoke() { + return client.getPendingSize() == 0 && client.getAsyncStore().getPendingSize() == 0 && binding.isDone(); + } + }; + while (true) { + Thread.sleep(1000); + if (!(condition.invoke())) { + continue; + } + Thread.sleep(1000); + if (!(condition.invoke())) { + continue; + } + Thread.sleep(1000); + if (!(condition.invoke())) { + continue; + } + break; + } + whenDone.run(); + } catch (InterruptedException e) { + } + } + }); + } + private static boolean check_d5jcfl_a0a0a0a2a0a0a6a0a0a0a0a0a0a0a0a0a1a0a0f0a0c(IConcept checkedDotOperand, IConcept projectConcept) { + if (null != checkedDotOperand) { + return checkedDotOperand.isSubConceptOf(projectConcept); + } + return false; + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Project$An = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, "org.modelix.model.repositoryconcepts.structure.Project"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelServerGroup_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelServerGroup_ActionGroup.java new file mode 100644 index 00000000..9f9c51f2 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelServerGroup_ActionGroup.java @@ -0,0 +1,21 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; + +public class ModelServerGroup_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.ModelServerGroup_ActionGroup"; + + public ModelServerGroup_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("ModelServerGroup", ID, plugin); + setIsInternal(false); + setPopup(false); + ModelServerGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.RemoveModelServer_Action"); + ModelServerGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.AddRepository_Action"); + ModelServerGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.ShowAuthenticationInfo_Action"); + ModelServerGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.Reconnect_Action"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixConfigurationSystemProperties.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixConfigurationSystemProperties.java new file mode 100644 index 00000000..77bf4ba0 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixConfigurationSystemProperties.java @@ -0,0 +1,54 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import org.modelix.common.PropertyOrEnv; +import java.util.Objects; +import org.apache.log4j.Level; + +public class ModelixConfigurationSystemProperties { + private static final Logger LOG = LogManager.getLogger(ModelixConfigurationSystemProperties.class); + public static String EXECUTION_MODE_SYSPROP = "modelix.executionMode"; + public static String LOAD_PERSISTENT_BINDIND_SYSPROP = "modelix.loadPersistentBinding"; + public static String EXPORT_PATH_SYSPROP = ModelixExportConfiguration.PATH; + public static String IMPORT_PATH_SYSPROP = "modelix.import.path"; + public static String CLOUD_REPOS_SYSPROP = "modelix.cloud.repos"; + + public static boolean shouldLoadPersistentBinding() { + String flagString = PropertyOrEnv.get(LOAD_PERSISTENT_BINDIND_SYSPROP); + if (flagString == null || flagString.isEmpty()) { + return true; + } + return Boolean.valueOf(flagString); + } + + public static EModelixExecutionMode getExecutionMode() { + String executionModeString = PropertyOrEnv.get(EXECUTION_MODE_SYSPROP); + EModelixExecutionMode executionMode = EModelixExecutionMode.DEFAULT; + if ((executionModeString == null || executionModeString.length() == 0)) { + String value = PropertyOrEnv.get("disable.autobinding"); + if (value != null && (Objects.equals(value.toLowerCase(), "true"))) { + executionMode = EModelixExecutionMode.INTEGRATION_TESTS; + } + + if (isNotEmptyString(PropertyOrEnv.get(EXPORT_PATH_SYSPROP))) { + executionMode = EModelixExecutionMode.MODEL_EXPORT; + } + } else { + try { + executionMode = EModelixExecutionMode.valueOf(executionModeString); + } catch (IllegalArgumentException ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("Unknown execution mode: " + executionModeString, ex); + } + } + } + System.setProperty(EXECUTION_MODE_SYSPROP, executionMode.name()); + return executionMode; + } + private static boolean isNotEmptyString(String str) { + return str != null && str.length() > 0; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixExportConfiguration.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixExportConfiguration.java new file mode 100644 index 00000000..6c8d6973 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixExportConfiguration.java @@ -0,0 +1,20 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + + +public class ModelixExportConfiguration { + private static final String PREFIX = "modelix.export."; + public static final String PATH = PREFIX + "path"; + public static final String STARTED = PREFIX + "started"; + public static final String DONE = PREFIX + "done"; + public static final String BRANCH_NAME = PREFIX + "branchName"; + public static final String REPOSITORY_ID = PREFIX + "repositoryId"; + public static final String SERVER_URL = PREFIX + "serverUrl"; + public static final String GRADLE_PLUGIN_SOCKET_PORT = PREFIX + "gradlePluginSocketPort"; + public static final String MAKE = PREFIX + "make"; + + private ModelixExportConfiguration() { + // prevent instantiation + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixImportConfiguration.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixImportConfiguration.java new file mode 100644 index 00000000..144d3dc6 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModelixImportConfiguration.java @@ -0,0 +1,17 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + + +public class ModelixImportConfiguration { + private static final String PREFIX = "modelix.import."; + public static final String STARTED = PREFIX + "started"; + public static final String DONE = PREFIX + "done"; + public static final String BRANCH_NAME = PREFIX + "branchName"; + public static final String REPOSITORY_ID = PREFIX + "repositoryId"; + public static final String SERVER_URL = PREFIX + "serverUrl"; + + private ModelixImportConfiguration() { + // prevent instantiation + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModuleAlreadyOnCloud_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModuleAlreadyOnCloud_Action.java new file mode 100644 index 00000000..0bbeeb1e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ModuleAlreadyOnCloud_Action.java @@ -0,0 +1,82 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import org.modelix.model.mpsplugin.CloudRepository; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.ModelCloudImportUtils; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import org.jetbrains.mps.openapi.module.SModule; + +public class ModuleAlreadyOnCloud_Action extends BaseAction { + private static final Icon ICON = null; + + private CloudRepository treeInRepository; + public ModuleAlreadyOnCloud_Action(CloudRepository treeInRepository_par) { + super("Copy on Cloud & Sync", "", ICON); + this.treeInRepository = treeInRepository_par; + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + boolean connected = ModuleAlreadyOnCloud_Action.this.treeInRepository.isConnected(); + event.getPresentation().setText(event.getData(MPSCommonDataKeys.MODULE).getModuleName() + " already in Cloud"); + try { + return connected && ModelCloudImportUtils.containsModule(ModuleAlreadyOnCloud_Action.this.treeInRepository, event.getData(MPSCommonDataKeys.MODULE)); + } catch (RuntimeException e) { + // This could happen because of repositories in invalid state. In this case let's ignore those repositories without preventing usage of other repositories + return false; + } + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + SModule p = event.getData(MPSCommonDataKeys.MODULE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + // noop + } + @NotNull + public String getActionId() { + StringBuilder res = new StringBuilder(); + res.append(super.getActionId()); + res.append("#"); + res.append(treeInRepository_State((CloudRepository) this.treeInRepository)); + res.append("!"); + return res.toString(); + } + public static String treeInRepository_State(CloudRepository object) { + return object.presentation(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Mpsplugin_ApplicationPlugin.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Mpsplugin_ApplicationPlugin.java new file mode 100644 index 00000000..82bba447 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Mpsplugin_ApplicationPlugin.java @@ -0,0 +1,74 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.applicationplugins.BaseApplicationPlugin; +import com.intellij.openapi.extensions.PluginId; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.ide.actions.ProjectActions_ActionGroup; +import jetbrains.mps.ide.actions.SolutionActions_ActionGroup; +import java.util.List; +import jetbrains.mps.plugins.part.ApplicationPluginPart; + +public class Mpsplugin_ApplicationPlugin extends BaseApplicationPlugin { + private final PluginId myId = PluginId.getId("org.modelix.model.mpsplugin"); + + public Mpsplugin_ApplicationPlugin() { + } + + @NotNull + public PluginId getId() { + return myId; + } + + public void createGroups() { + // actions w/o parameters + addAction(new AddBranch_Action()); + addAction(new AddModelNode_Action()); + addAction(new AddModelServer_Action()); + addAction(new AddModuleNode_Action()); + addAction(new AddProjectBinding_Action()); + addAction(new AddProjectNode_Action()); + addAction(new AddRepository_Action()); + addAction(new AddTransientModuleBinding_Action()); + addAction(new CheckoutAndSyncModule_Action()); + addAction(new CheckoutModule_Action()); + addAction(new DeleteModule_Action()); + addAction(new DeleteProject_Action()); + addAction(new GetCloudRepositorySize_Action()); + addAction(new LoadHistoryForBranch_Action()); + addAction(new LoadHistoryForRepository_Action()); + addAction(new NavigateToMpsNode_Action()); + addAction(new Reconnect_Action()); + addAction(new RemoveModelServer_Action()); + addAction(new RemoveRepository_Action()); + addAction(new RemoveTransientModuleBinding_Action()); + addAction(new ShowAuthenticationInfo_Action()); + addAction(new ShowProperties_Action()); + addAction(new ShowReferences_Action()); + addAction(new StoreAllModules_Action()); + addAction(new SwitchBranch_Action()); + addAction(new Unbind_Action()); + // groups + addGroup(new CloudActionsForPhysicalModulesCloudActions_ActionGroup(this)); + addGroup(new CloudActionsForPhysicalModules_ActionGroup(this)); + addGroup(new CloudActionsForPhysicalProjectsCloudActions_ActionGroup(this)); + addGroup(new CloudActionsForPhysicalProjects_ActionGroup(this)); + addGroup(new CloudBindingGroup_ActionGroup(this)); + addGroup(new CloudBranchGroup_ActionGroup(this)); + addGroup(new CloudNodeGroupAddChild_ActionGroup(this)); + addGroup(new CloudNodeGroupSetProperty_ActionGroup(this)); + addGroup(new CloudNodeGroup_ActionGroup(this)); + addGroup(new CloudRootGroup_ActionGroup(this)); + addGroup(new ModelServerGroup_ActionGroup(this)); + addGroup(new RepositoryGroup_ActionGroup(this)); + } + public void adjustRegularGroups() { + insertGroupIntoAnother(CloudActionsForPhysicalProjects_ActionGroup.ID, ProjectActions_ActionGroup.ID, ProjectActions_ActionGroup.LABEL_ID_projectNew); + insertGroupIntoAnother(CloudActionsForPhysicalModules_ActionGroup.ID, SolutionActions_ActionGroup.ID, SolutionActions_ActionGroup.LABEL_ID_contents); + } + @Override + public void fillCustomParts(List parts) { + parts.add(new ApplicationPlugin_AppPluginPart()); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Mpsplugin_ProjectPlugin.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Mpsplugin_ProjectPlugin.java new file mode 100644 index 00000000..e5bac768 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Mpsplugin_ProjectPlugin.java @@ -0,0 +1,25 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.projectplugins.BaseProjectPlugin; +import java.util.List; +import jetbrains.mps.ide.tools.BaseTool; +import com.intellij.openapi.project.Project; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import jetbrains.mps.plugins.part.ProjectPluginPart; + +public class Mpsplugin_ProjectPlugin extends BaseProjectPlugin { + public Mpsplugin_ProjectPlugin() { + } + public List initAllTools1(Project project) { + List tools = ListSequence.fromList(new ArrayList()); + ListSequence.fromList(tools).addElement(new CloudHistoryTool_Tool(project)); + ListSequence.fromList(tools).addElement(new CloudTool_Tool(project)); + return tools; + } + public void fillCustomParts(List parts) { + parts.add(new ProjectPlugin_ProjectPluginPart()); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/NavigateToMpsNode_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/NavigateToMpsNode_Action.java new file mode 100644 index 00000000..50874b18 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/NavigateToMpsNode_Action.java @@ -0,0 +1,169 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNodeBinding; +import kotlin.jvm.functions.Function0; +import org.modelix.model.mpsplugin.MPSNodeMapping; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.api.INode; +import org.modelix.model.mpsplugin.INodeUtils; +import com.intellij.openapi.ui.Messages; +import org.jetbrains.mps.openapi.module.SRepository; +import jetbrains.mps.ide.project.ProjectHelper; +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.internal.collections.runtime.Sequence; +import java.util.Objects; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.model.SNode; +import jetbrains.mps.openapi.navigation.NavigationSupport; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class NavigateToMpsNode_Action extends BaseAction { + private static final Icon ICON = null; + + public NavigateToMpsNode_Action() { + super("Navigate to Corresponding MPS Node", "", ICON); + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.NONE); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + if (!(TreeNodeClassification.isProperNode(event.getData(MPSCommonDataKeys.TREE_NODE)))) { + return false; + } + final CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + CloudRepository treeInRepository = CloudNodeTreeNodeBinding.getTreeInRepository(nodeTreeNode); + return treeInRepository.computeRead(new Function0() { + public Boolean invoke() { + return MPSNodeMapping.isMappedToMpsNode(nodeTreeNode.getNode()); + } + }); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + final CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + final CloudRepository treeInRepository = CloudNodeTreeNodeBinding.getTreeInRepository(nodeTreeNode); + // I need to know in which module to look for this node + + treeInRepository.runRead(new Runnable() { + public void run() { + final String mpsNodeId = treeInRepository.computeRead(new Function0() { + public String invoke() { + return MPSNodeMapping.mappedMpsNodeID(nodeTreeNode.getNode()); + } + }); + INode cloudModule = INodeUtils.containingModule(nodeTreeNode.getNode()); + if (cloudModule == null) { + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "No containing module found", "Error navigating to MPS node"); + return; + } + INode cloudModel = INodeUtils.containingModel(nodeTreeNode.getNode()); + if (cloudModel == null) { + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "No containing model found", "Error navigating to MPS node"); + return; + } + final String moduleId = cloudModule.getPropertyValue(PROPS.id$7MjP.getName()); + if (moduleId == null) { + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "No module id", "Error navigating to MPS node"); + return; + } + final String modelId = cloudModel.getPropertyValue(PROPS.id$lDUo.getName()); + if (modelId == null) { + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "No model id", "Error navigating to MPS node"); + return; + } + final SRepository repo = ProjectHelper.toMPSProject(event.getData(CommonDataKeys.PROJECT)).getRepository(); + repo.getModelAccess().runReadAction(new Runnable() { + public void run() { + for (SModule module : Sequence.fromIterable(repo.getModules())) { + if (Objects.equals(module.getModuleId().toString(), moduleId)) { + for (SModel model : Sequence.fromIterable(module.getModels())) { + if (Objects.equals(model.getModelId().toString(), modelId)) { + SNode node = NavigateToMpsNode_Action.this.findNodeInModel(model, mpsNodeId, event); + if (node == null) { + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "No node found: " + mpsNodeId, "Error navigating to MPS node"); + return; + } else { + NavigationSupport.getInstance().openNode(ProjectHelper.toMPSProject(event.getData(CommonDataKeys.PROJECT)), node, false, true); + return; + } + } + } + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "No model found: " + modelId, "Error navigating to MPS node"); + return; + } + } + Messages.showErrorDialog(event.getData(CommonDataKeys.PROJECT), "No module found: " + moduleId, "Error navigating to MPS node"); + } + }); + } + }); + } + /*package*/ SNode findNodeInModel(SModel model, String nodeId, final AnActionEvent event) { + for (SNode root : Sequence.fromIterable(model.getRootNodes())) { + SNode res = NavigateToMpsNode_Action.this.findNodeInNode(root, nodeId, event); + if (res != null) { + return res; + } + } + return null; + } + /*package*/ SNode findNodeInNode(SNode node, String nodeId, final AnActionEvent event) { + if (Objects.equals(node.getNodeId().toString(), nodeId)) { + return node; + } + for (SNode child : Sequence.fromIterable(node.getChildren())) { + SNode res = NavigateToMpsNode_Action.this.findNodeInNode(child, nodeId, event); + if (res != null) { + return res; + } + } + return null; + } + + private static final class PROPS { + /*package*/ static final SProperty id$7MjP = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, 0x3aa34013f2a802e0L, "id"); + /*package*/ static final SProperty id$lDUo = MetaAdapterFactory.getProperty(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50cL, 0x244b85440ee67212L, "id"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/PersistedBindingConfiguration.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/PersistedBindingConfiguration.java new file mode 100644 index 00000000..256bd03a --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/PersistedBindingConfiguration.java @@ -0,0 +1,465 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import java.util.Map; +import com.intellij.openapi.project.Project; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import jetbrains.mps.ide.project.ProjectHelper; +import java.util.concurrent.ConcurrentMap; +import de.slisson.mps.reflection.runtime.ReflectionUtil; +import com.intellij.serviceContainer.ComponentManagerImpl; +import java.util.function.Consumer; +import org.modelix.model.mpsplugin.ModelServerConnection; +import java.util.function.Predicate; +import java.util.Objects; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.ModuleBinding; +import org.modelix.model.mpsplugin.TransientModuleBinding; +import org.modelix.model.mpsplugin.ProjectModuleBinding; +import org.modelix.model.api.IBranch; +import org.modelix.model.api.INode; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import kotlin.Unit; +import org.modelix.model.area.PArea; +import kotlin.jvm.functions.Function0; +import org.modelix.model.api.PNodeAdapter; +import org.jetbrains.mps.openapi.model.SNode; +import org.apache.log4j.Level; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import org.modelix.model.mpsplugin.ModelServerConnections; +import jetbrains.mps.baseLanguage.logging.runtime.model.LoggingRuntime; +import java.util.Set; +import org.modelix.model.mpsplugin.SharedExecutors; +import jetbrains.mps.internal.collections.runtime.Sequence; +import org.jetbrains.mps.openapi.module.SModule; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.INodeUtils; +import org.modelix.model.mpsplugin.SyncDirection; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; + +public class PersistedBindingConfiguration { + private static final Logger LOG = LogManager.getLogger(PersistedBindingConfiguration.class); + + private static Map instances = MapSequence.fromMap(new HashMap()); + + public static PersistedBindingConfiguration getInstance(Project project) { + if (!(MapSequence.fromMap(instances).containsKey(project))) { + MapSequence.fromMap(instances).put(project, new PersistedBindingConfiguration(project)); + } + return MapSequence.fromMap(instances).get(project); + } + + public static PersistedBindingConfiguration getInstance(jetbrains.mps.project.Project project) { + return getInstance(ProjectHelper.toIdeaProject(project)); + } + + public static void disposeInstance(Project project) { + PersistedBindingConfiguration instance = MapSequence.fromMap(instances).removeKey(project); + if (instance != null) { + instance.dispose(); + } + } + + private Project project; + + private PersistedBindingConfiguration(Project project) { + this.project = project; + } + + public void dispose() { + ConcurrentMap, Object> lightServices = ((ConcurrentMap, Object>) ReflectionUtil.readField(ComponentManagerImpl.class, ((ComponentManagerImpl) project), "lightServices")); + lightServices.remove(CloudResourcesConfigurationComponent.class); + + } + + public String describeState() { + return readState().toString(); + } + + public void applyToProject() { + addModelServersAsSpecifiedInPersistedBindingConfiguration(); + bindTransientModulesAsSpecifiedInPersistedConfiguration(); + bindMappedModulesAsSpecifiedInPersistedConfiguration(); + } + + public boolean isEmpty() { + CloudResourcesConfigurationComponent.State state = readState(); + if (!(state.modelServers.isEmpty())) { + return false; + } + if (!(state.mappedModules.isEmpty())) { + return false; + } + if (!(state.transientModules.isEmpty())) { + return false; + } + if (!(state.transientProjects.isEmpty())) { + return false; + } + return true; + } + + public boolean hasMappedModule(String moduleName) { + CloudResourcesConfigurationComponent.State state = readState(); + for (String mm : state.mappedModules) { + if (mm.endsWith("#" + moduleName)) { + return true; + } + } + return false; + } + + public void clear() { + modifyState(new Consumer() { + public void accept(CloudResourcesConfigurationComponent.State state) { + state.modelServers.clear(); + state.mappedModules.clear(); + state.transientModules.clear(); + state.transientProjects.clear(); + } + }); + assert isEmpty(); + } + + private CloudResourcesConfigurationComponent.State readState() { + CloudResourcesConfigurationComponent cloudResourcesConfigurationComponent = project.getService(CloudResourcesConfigurationComponent.class); + CloudResourcesConfigurationComponent.State state = cloudResourcesConfigurationComponent.getState(); + return state; + } + + private void modifyState(Consumer modifier) { + CloudResourcesConfigurationComponent cloudResourcesConfigurationComponent = project.getService(CloudResourcesConfigurationComponent.class); + CloudResourcesConfigurationComponent.State state = readState(); + modifier.accept(state); + cloudResourcesConfigurationComponent.loadState(state); + } + + public void addModelServer(final ModelServerConnection modelServer) { + modifyState(new Consumer() { + public void accept(CloudResourcesConfigurationComponent.State state) { + state.modelServers.add(modelServer.getBaseUrl()); + } + }); + } + + public boolean isModelServerPresent(String url) { + return readState().modelServers.contains(url); + } + + public void ensureModelServerIsPresent(final ModelServerConnection modelServer) { + if (!(isModelServerPresent(modelServer.getBaseUrl()))) { + modifyState(new Consumer() { + public void accept(CloudResourcesConfigurationComponent.State state) { + state.modelServers.add(modelServer.getBaseUrl()); + } + }); + } + } + + + public void removeModelServer(final ModelServerConnection modelServer) { + modifyState(new Consumer() { + public void accept(CloudResourcesConfigurationComponent.State state) { + state.modelServers.removeIf(new Predicate() { + public boolean test(String url) { + return Objects.equals(url, modelServer.getBaseUrl()); + } + }); + state.transientModules.removeIf(new Predicate() { + public boolean test(String moduleStr) { + return moduleStr.startsWith(modelServer.getBaseUrl() + "#"); + } + }); + } + }); + } + + public void addTransientBoundModule(CloudRepository repositoryInModelServer, CloudNodeTreeNode nodeTreeNode) { + addTransientBoundModule(repositoryInModelServer, nodeTreeNode.getBranch(), nodeTreeNode.getNode()); + } + + public void removeTransientBoundModule(CloudRepository repositoryInModelServer, CloudNodeTreeNode nodeTreeNode) { + removeTransientBoundModule(repositoryInModelServer, nodeTreeNode.getBranch(), nodeTreeNode.getNode()); + } + + public void removeBoundModule(CloudRepository repositoryInModelServer, ModuleBinding moduleBinding) { + if (moduleBinding instanceof TransientModuleBinding) { + TransientModuleBinding transientModuleBinding = ((TransientModuleBinding) moduleBinding); + removeMappedBoundModule(repositoryInModelServer, transientModuleBinding.getModuleNodeId()); + } else if (moduleBinding instanceof ProjectModuleBinding) { + ProjectModuleBinding mappedModuleBinding = ((ProjectModuleBinding) moduleBinding); + removeMappedModule(repositoryInModelServer, mappedModuleBinding); + } else { + throw new UnsupportedOperationException("Unsupported ModuleBinding " + moduleBinding.getClass()); + } + } + + public void removeMappedModule(CloudRepository repositoryInModelServer, ProjectModuleBinding binding) { + removeMappedBoundModule(repositoryInModelServer, binding.getModuleNodeId()); + } + + public void addTransientBoundModule(final CloudRepository repositoryInModelServer, final IBranch branch, final INode cloudNode) { + modifyState(new _Adapters._return_P1_E0_to_Consumer_adapter(new _FunctionTypes._return_P1_E0() { + public Unit invoke(final CloudResourcesConfigurationComponent.State state) { + return new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + String moduleName = ((PNodeAdapter) cloudNode).getPropertyValue("name"); + state.transientModules.add(repositoryInModelServer.completeId() + "#" + moduleName); + return Unit.INSTANCE; + } + }); + } + })); + } + + public void removeTransientBoundModule(final CloudRepository repositoryInModelServer, final IBranch branch, final INode cloudNode) { + modifyState(new _Adapters._return_P1_E0_to_Consumer_adapter(new _FunctionTypes._return_P1_E0() { + public Unit invoke(final CloudResourcesConfigurationComponent.State state) { + return new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + String moduleName = ((PNodeAdapter) cloudNode).getPropertyValue("name"); + String transientModuleDesc = repositoryInModelServer.completeId() + "#" + moduleName; + state.transientModules.remove(transientModuleDesc); + return Unit.INSTANCE; + } + }); + } + })); + } + + public void removeTransientBoundModule(final CloudRepository repositoryInModelServer, final IBranch branch, final long nodeId) { + modifyState(new _Adapters._return_P1_E0_to_Consumer_adapter(new _FunctionTypes._return_P1_E0() { + public Unit invoke(final CloudResourcesConfigurationComponent.State state) { + return new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + String moduleName = branch.getReadTransaction().getProperty(nodeId, "name"); + String transientModuleDesc = repositoryInModelServer.completeId() + "#" + moduleName; + state.transientModules.remove(transientModuleDesc); + return Unit.INSTANCE; + } + }); + } + })); + } + + public void removeMappedBoundModule(final CloudRepository repositoryInModelServer, final long nodeId) { + final IBranch branch = repositoryInModelServer.getActiveBranch().getBranch(); + modifyState(new _Adapters._return_P1_E0_to_Consumer_adapter(new _FunctionTypes._return_P1_E0() { + public Unit invoke(final CloudResourcesConfigurationComponent.State state) { + return new PArea(branch).executeRead(new Function0() { + public Unit invoke() { + String moduleName = branch.getReadTransaction().getProperty(nodeId, "name"); + String moduleDesc = repositoryInModelServer.completeId() + "#" + moduleName; + state.mappedModules.remove(moduleDesc); + return Unit.INSTANCE; + } + }); + } + })); + } + + public void addTransientBoundModule(CloudRepository repositoryInModelServer, IBranch branch, long cloudNodeId) { + addTransientBoundModule(repositoryInModelServer, branch, new PNodeAdapter(cloudNodeId, branch)); + } + + public void addTransientBoundProject(final CloudRepository repositoryInModelServer, SNode cloudProject) { + modifyState(new Consumer() { + public void accept(final CloudResourcesConfigurationComponent.State state) { + repositoryInModelServer.runRead(new Runnable() { + public void run() { + state.transientProjects.add(repositoryInModelServer.completeId()); + } + }); + } + }); + } + + public void addTransientBoundModule(final CloudRepository repositoryInModelServer, final PNodeAdapter nodeTreeNode) { + modifyState(new _Adapters._return_P1_E0_to_Consumer_adapter(new _FunctionTypes._return_P1_E0() { + public Unit invoke(final CloudResourcesConfigurationComponent.State state) { + return new PArea(nodeTreeNode.getBranch()).executeRead(new Function0() { + public Unit invoke() { + String moduleName = ((PNodeAdapter) nodeTreeNode).getPropertyValue("name"); + state.transientModules.add(repositoryInModelServer.completeId() + "#" + moduleName); + return Unit.INSTANCE; + } + }); + } + })); + } + + public void addMappedBoundModule(final CloudRepository repositoryInModelServer, final PNodeAdapter nodeTreeNode) { + if (repositoryInModelServer == null) { + throw new IllegalArgumentException("treeInRepository should not be null"); + } + modifyState(new _Adapters._return_P1_E0_to_Consumer_adapter(new _FunctionTypes._return_P1_E0() { + public Unit invoke(final CloudResourcesConfigurationComponent.State state) { + return new PArea(nodeTreeNode.getBranch()).executeRead(new Function0() { + public Unit invoke() { + String moduleName = ((PNodeAdapter) nodeTreeNode).getPropertyValue(PROPS.name$MnvL.getName()); + if (moduleName == null) { + throw new IllegalStateException("module should not have null name"); + } + state.mappedModules.add(repositoryInModelServer.completeId() + "#" + moduleName); + return Unit.INSTANCE; + } + }); + } + })); + } + + private void addModelServersAsSpecifiedInPersistedBindingConfiguration() { + CloudResourcesConfigurationComponent.State state = readState(); + for (String repoUrl : state.modelServers) { + System.out.println("addModelServersAsSpecifiedInPersistedBindingConfiguration " + repoUrl); + ModelServerConnection cloudRepository = ensureModelServerIsPresent(repoUrl); + } + } + + private void bindTransientModulesAsSpecifiedInPersistedConfiguration() { + CloudResourcesConfigurationComponent.State state = readState(); + for (String moduleStr : state.transientModules) { + final String[] parts = moduleStr.split("#"); + if (parts.length != 2) { + if (LOG.isEnabledFor(Level.FATAL)) { + LOG.fatal("The configuration of Modelix is not correct, please check .mps/cloudResources.xml. Module entry: " + moduleStr, new RuntimeException()); + } + continue; + } + final CloudRepository repositoryInModelServer = CloudRepository.fromPresentationString(parts[0]); + ModelServerConnection modelServer = ensureModelServerIsPresent(repositoryInModelServer.getModelServer().getBaseUrl()); + + withConnectedCloudRepo(modelServer, new Consumer() { + public void accept(ModelServerConnection msc) { + bindToTransientModules(repositoryInModelServer, SetSequence.fromSetAndArray(new HashSet(), parts[1])); + } + }); + } + } + + private void bindMappedModulesAsSpecifiedInPersistedConfiguration() { + CloudResourcesConfigurationComponent.State state = readState(); + for (String moduleStr : state.mappedModules) { + final String[] parts = moduleStr.split("#"); + if (parts.length != 2) { + if (LOG.isEnabledFor(Level.FATAL)) { + LOG.fatal("The configuration of Modelix is not correct, please check .mps/cloudResources.xml. Module entry: " + moduleStr, new RuntimeException()); + } + continue; + } + final CloudRepository repositoryInModelServer = CloudRepository.fromPresentationString(parts[0]); + ModelServerConnection modelServer = ensureModelServerIsPresent(repositoryInModelServer.getModelServer().getBaseUrl()); + + withConnectedCloudRepo(modelServer, new Consumer() { + public void accept(ModelServerConnection msc) { + bindToMappedModules(repositoryInModelServer, SetSequence.fromSetAndArray(new HashSet(), parts[1])); + } + }); + } + } + + + private static ModelServerConnection ensureModelServerIsPresent(String url) { + return ModelServerConnections.getInstance().ensureModelServerIsPresent(url); + } + + private static void withConnectedCloudRepoHelper(final ModelServerConnection modelServer, final Consumer consumer, final int nAttempts) { + if (modelServer.isConnected()) { + consumer.accept(modelServer); + } else { + if (nAttempts <= 0) { + LoggingRuntime.logMsgView(Level.ERROR, "Unable to connect to Modelix server. Modelix configuration aborted", PersistedBindingConfiguration.class, null, null); + return; + } + modelServer.reconnect(); + new Thread(new Runnable() { + public void run() { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + withConnectedCloudRepoHelper(modelServer, consumer, nAttempts - 1); + } + }).start(); + } + } + + /** + * Sometimes we need to wait for the repository to be connected. This is the case for example on starting the plugin. + */ + private static void withConnectedCloudRepo(final ModelServerConnection modelServer, final Consumer consumer) { + PersistedBindingConfiguration.withConnectedCloudRepoHelper(modelServer, consumer, 20); + } + + /** + * FIXME we should probably not identify modules by name but some unique identifier instead + * + * @param repositoryInModelServer + * @param modulesToBind + */ + private static void bindToTransientModules(final CloudRepository repositoryInModelServer, final Set modulesToBind) { + SharedExecutors.FIXED.execute(new Runnable() { + public void run() { + repositoryInModelServer.runRead(new Consumer() { + public void accept(PNodeAdapter rootNode) { + for (INode child : Sequence.fromIterable(rootNode.getAllChildren())) { + String name = child.getPropertyValue("name"); + if (SetSequence.fromSet(modulesToBind).contains(name)) { + repositoryInModelServer.addTransientModuleBinding(child); + } + } + } + }); + } + }); + } + + /** + * FIXME we should probably not identify modules by name but some unique identifier instead + * + * @param repositoryInModelServer + * @param modulesToBind + */ + private void bindToMappedModules(final CloudRepository repositoryInModelServer, final Set modulesToBind) { + SharedExecutors.FIXED.execute(new Runnable() { + public void run() { + repositoryInModelServer.runRead(new Consumer() { + public void accept(PNodeAdapter rootNode) { + for (INode child : Sequence.fromIterable(rootNode.getAllChildren())) { + String name = child.getPropertyValue("name"); + if (SetSequence.fromSet(modulesToBind).contains(name)) { + SModule physicalModule = findPhysicalModule(name); + if (physicalModule == null) { + Messages.showErrorDialog(project, "We cannot instantiate the mapped binding to " + name + " because the module is missing", "Error on mapped binding"); + } else { + repositoryInModelServer.addBinding(new ProjectModuleBinding(INodeUtils.nodeIdAsLong(child), physicalModule, SyncDirection.TO_MPS)); + } + } + } + } + }); + } + }); + } + + private SModule findPhysicalModule(String moduleName) { + for (SModule physicalModule : ListSequence.fromList(ProjectHelper.toMPSProject(project).getProjectModules())) { + if (Objects.equals(physicalModule.getModuleName(), moduleName)) { + return physicalModule; + } + } + return null; + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectMakeRunner.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectMakeRunner.java new file mode 100644 index 00000000..3645859b --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectMakeRunner.java @@ -0,0 +1,156 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import java.util.function.Consumer; +import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; +import java.util.List; +import jetbrains.mps.messages.IMessage; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import org.apache.log4j.Level; +import jetbrains.mps.project.Project; +import jetbrains.mps.messages.IMessageHandler; +import java.util.LinkedList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.make.MakeSession; +import java.util.ArrayList; +import jetbrains.mps.ide.make.actions.MakeActionParameters; +import jetbrains.mps.make.IMakeService; +import jetbrains.mps.make.MakeServiceComponent; +import jetbrains.mps.make.resources.IResource; +import org.jetbrains.mps.openapi.model.SModel; +import jetbrains.mps.smodel.ModelAccessHelper; +import jetbrains.mps.util.Computable; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ITranslator2; +import jetbrains.mps.smodel.resources.MResource; +import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; +import java.util.concurrent.Future; +import jetbrains.mps.make.script.IResult; +import jetbrains.mps.internal.collections.runtime.IterableUtils; +import jetbrains.mps.internal.collections.runtime.ISelector; + +public class ProjectMakeRunner { + private static final Logger LOG = LogManager.getLogger(ProjectMakeRunner.class); + public ProjectMakeRunner() { + } + + public static Consumer>> DEFAULT_SUCCESS_CONSUMER = new Consumer>>() { + @Override + public void accept(Tuples._2> res) { + if (LOG.isDebugEnabled()) { + LOG.debug("Make messages:"); + } + for (IMessage message : ListSequence.fromList(res._1())) { + if (LOG.isDebugEnabled()) { + LOG.debug(" " + message.getKind() + " " + message.getText()); + } + } + if (LOG.isInfoEnabled()) { + LOG.info("Make Project Success: " + res._0()); + } + } + }; + public static Consumer>> DEFAULT_FAILURE_CONSUMER = new Consumer>>() { + @Override + public void accept(Tuples._2> res) { + if (LOG.isDebugEnabled()) { + LOG.debug("Make messages:"); + } + for (IMessage message : ListSequence.fromList(res._1())) { + if (LOG.isInfoEnabled()) { + LOG.info(" " + message.getKind() + " " + message.getText()); + } + } + if (LOG.isEnabledFor(Level.WARN)) { + LOG.warn("Make Project Failure: " + res._0()); + } + } + }; + + public static void execute(final Project mpsProject, boolean cleanMake) { + execute(mpsProject, cleanMake, null, DEFAULT_SUCCESS_CONSUMER, DEFAULT_FAILURE_CONSUMER); + } + + private static class MyMessageHandler implements IMessageHandler { + private List messages = ListSequence.fromList(new LinkedList()); + + + @Override + public void handle(@NotNull IMessage message) { + ListSequence.fromList(messages).addElement(message); + } + } + + public static void execute(final Project mpsProject, final boolean cleanMake, List modulesToBuild, final Consumer>> success, final Consumer>> failure) { + final MyMessageHandler messageHandler = new MyMessageHandler(); + MakeSession session = new MakeSession(mpsProject, messageHandler, cleanMake); + if (modulesToBuild == null) { + modulesToBuild = ListSequence.fromListWithValues(new ArrayList(), (Iterable) mpsProject.getProjectModules()); + } + final MakeActionParameters params = new MakeActionParameters(mpsProject).modules(modulesToBuild).cleanMake(cleanMake); + final IMakeService makeService = mpsProject.getComponent(MakeServiceComponent.class).get(); + if (makeService.openNewSession(session)) { + // empty collection is fine, it's up to make service to report there's nothing to do (odd, but fine for now. Action could have do that instead) + // + // ModelValidatorAdapter needs to be refactored not to mix model checking code with UI, which might request + // write access e.g. on focus lost and eventually lead to 'write from read' issue like + // FIXME https://youtrack.jetbrains.com/issue/MPS-24020. Proper fix is to split model check into read, and results reporting into EDT. + // For 3.4 RC, we decided to go with a hack and let SModel instances cross model read boundary + List inputRes = null; + final ArrayList models = new ArrayList(); + try { + inputRes = new ModelAccessHelper(mpsProject.getModelAccess()).runReadAction(new Computable>() { + public List compute() { + List rv = Sequence.fromIterable(params.collectInput()).toListSequence(); + models.addAll(ListSequence.fromList(rv).translate(new ITranslator2() { + public Iterable translate(IResource it) { + return ((MResource) it).models(); + } + }).toListSequence()); + return rv; + } + }); + + } catch (RuntimeException e) { + makeService.closeSession(session); + e.printStackTrace(); + failure.accept(MultiTuple.>from(e.getMessage(), messageHandler.messages)); + return; + } + + if (inputRes != null) { + final Future result = makeService.make(session, inputRes); + Thread t = new Thread(new Runnable() { + @Override + public void run() { + try { + IResult resultValue = result.get(); + String resDesc = IterableUtils.join(Sequence.fromIterable(resultValue.output()).select(new ISelector() { + public String select(IResource it) { + return it.describe(); + } + }), ", "); + if (resultValue.isSucessful()) { + success.accept(MultiTuple.>from("make succeeded. Resource: " + resDesc, messageHandler.messages)); + } else { + failure.accept(MultiTuple.>from("make failed. Resources: " + resDesc, messageHandler.messages)); + } + } catch (Throwable t) { + t.printStackTrace(); + failure.accept(MultiTuple.>from(t.getMessage(), messageHandler.messages)); + } + } + }); + t.start(); + } else { + makeService.closeSession(session); + failure.accept(MultiTuple.>from("no input", messageHandler.messages)); + } + } + } + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectManagerExtensions.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectManagerExtensions.java new file mode 100644 index 00000000..6afafcad --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectManagerExtensions.java @@ -0,0 +1,34 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import com.intellij.openapi.project.ProjectManager; +import java.util.function.Consumer; +import jetbrains.mps.project.Project; +import java.util.List; +import jetbrains.mps.project.ProjectManagerListener; +import org.jetbrains.annotations.NotNull; + +public class ProjectManagerExtensions { + public ProjectManagerExtensions() { + } + public static void withTheOnlyProject(final ProjectManager _this, final Consumer stuffToDoOnceWeGetAProject) { + List openProjects = jetbrains.mps.project.ProjectManager.getInstance().getOpenedProjects(); + if (openProjects.size() == 0) { + jetbrains.mps.project.ProjectManager.getInstance().addProjectListener(new ProjectManagerListener() { + @Override + public void projectOpened(@NotNull Project project) { + stuffToDoOnceWeGetAProject.accept(project); + } + @Override + public void projectClosed(@NotNull Project project) { + // nothing to do here + } + }); + } else if (openProjects.size() == 1) { + stuffToDoOnceWeGetAProject.accept(openProjects.get(0)); + } else { + throw new IllegalStateException("Exactly one open project expected. Open projects: " + openProjects); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectPlugin_ProjectPluginPart.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectPlugin_ProjectPluginPart.java new file mode 100644 index 00000000..6659d7f8 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ProjectPlugin_ProjectPluginPart.java @@ -0,0 +1,45 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.part.ProjectPluginPart; +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import jetbrains.mps.project.MPSProject; +import org.modelix.model.mpsplugin.projectview.CloudProjectViewExtension; +import jetbrains.mps.ide.project.ProjectHelper; + +public class ProjectPlugin_ProjectPluginPart extends ProjectPluginPart { + private static final Logger LOG = LogManager.getLogger(ProjectPlugin_ProjectPluginPart.class); + public ProjectPlugin_ProjectPluginPart() { + } + @Override + public void init(MPSProject project) { + EModelixExecutionMode executionMode = ModelixConfigurationSystemProperties.getExecutionMode(); + if (executionMode == EModelixExecutionMode.MODEL_EXPORT) { + return; + } + + CloudProjectViewExtension.getInstance(project).init(); + if (ModelixConfigurationSystemProperties.shouldLoadPersistentBinding()) { + if (LOG.isDebugEnabled()) { + LOG.debug("APPLYING PROJECT PLUGIN - PERSISTED BINDING CONFIGURATION. Loading persisted binding is enabled"); + } + PersistedBindingConfiguration.getInstance(ProjectHelper.toIdeaProject(project)).applyToProject(); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("APPLYING PROJECT PLUGIN - PERSISTED BINDING CONFIGURATION. Loading persisted binding disabled, skipping"); + } + } + } + @Override + public void dispose(MPSProject project) { + EModelixExecutionMode executionMode = ModelixConfigurationSystemProperties.getExecutionMode(); + if (executionMode == EModelixExecutionMode.MODEL_EXPORT) { + return; + } + + CloudProjectViewExtension.getInstance(project).dispose(); + PersistedBindingConfiguration.disposeInstance(ProjectHelper.toIdeaProject(project)); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Reconnect_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Reconnect_Action.java new file mode 100644 index 00000000..43cae20f --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Reconnect_Action.java @@ -0,0 +1,65 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.ModelServerTreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; + +public class Reconnect_Action extends BaseAction { + private static final Icon ICON = null; + + public Reconnect_Action() { + super("Reconnect", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + if (!(event.getData(MPSCommonDataKeys.TREE_NODE) instanceof ModelServerTreeNode)) { + return false; + } + ModelServerConnection modelServer = ((ModelServerTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)).getModelServer(); + return !(modelServer.isConnected()); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + ModelServerConnection modelServer = ((ModelServerTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)).getModelServer(); + modelServer.reconnect(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveModelServer_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveModelServer_Action.java new file mode 100644 index 00000000..02caa7da --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveModelServer_Action.java @@ -0,0 +1,69 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.ModelServerTreeNode; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import com.intellij.openapi.ui.Messages; +import org.modelix.model.mpsplugin.CloudIcons; +import org.modelix.model.mpsplugin.ModelServerConnections; + +public class RemoveModelServer_Action extends BaseAction { + private static final Icon ICON = null; + + public RemoveModelServer_Action() { + super("Remove Model Server", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return event.getData(MPSCommonDataKeys.TREE_NODE) instanceof ModelServerTreeNode; + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + ModelServerConnection modelServer = ((ModelServerTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)).getModelServer(); + + int answer = Messages.showOkCancelDialog(event.getData(CommonDataKeys.PROJECT), "Remove " + modelServer.getBaseUrl() + "?", "Remove Model Server", "Remove", "Keep", CloudIcons.REPOSITORY_ICON); + if (answer == Messages.OK) { + ModelServerConnections.getInstance().removeModelServer(modelServer); + PersistedBindingConfiguration.getInstance(event.getData(CommonDataKeys.PROJECT)).removeModelServer(modelServer); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveRepository_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveRepository_Action.java new file mode 100644 index 00000000..e7e05020 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveRepository_Action.java @@ -0,0 +1,47 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import javax.swing.tree.TreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; + +public class RemoveRepository_Action extends BaseAction { + private static final Icon ICON = null; + + public RemoveRepository_Action() { + super("Remove Repository", "", ICON); + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + RepositoryTreeNode repositoryNode = (RepositoryTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + ModelServerConnection modelServer = repositoryNode.getModelServer(); + modelServer.removeRepository(repositoryNode.getRepositoryId().getId()); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveTransientModuleBinding_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveTransientModuleBinding_Action.java new file mode 100644 index 00000000..a9a5586c --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RemoveTransientModuleBinding_Action.java @@ -0,0 +1,75 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.TreeNodeBinding; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.TransientModuleBinding; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.mpsplugin.history.ModelServerTreeNode; +import org.modelix.model.mpsplugin.CloudRepository; + +public class RemoveTransientModuleBinding_Action extends BaseAction { + private static final Icon ICON = null; + + public RemoveTransientModuleBinding_Action() { + super("Unbind from Transient Module", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isModuleNode(event.getData(MPSCommonDataKeys.TREE_NODE)) && TreeNodeBinding.isBoundAsModule(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + RemoveTransientModuleBinding_Action.this.removeTransientModuleBinding(event.getData(MPSCommonDataKeys.TREE_NODE), event.getData(CommonDataKeys.PROJECT), TreeNodeBinding.getTransientModuleBinding(event.getData(MPSCommonDataKeys.TREE_NODE)), event); + } + public void removeTransientModuleBinding(TreeNode treeNode, Project mpsProject, TransientModuleBinding transientModuleBinding, final AnActionEvent event) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) treeNode; + RepositoryId repositoryId = nodeTreeNode.getAncestor(RepositoryTreeNode.class).getRepositoryId(); + ModelServerConnection modelServerConnection = nodeTreeNode.getAncestor(ModelServerTreeNode.class).getModelServer(); + modelServerConnection.removeBinding(transientModuleBinding); + CloudRepository treeInRepository = new CloudRepository(modelServerConnection, repositoryId); + PersistedBindingConfiguration.getInstance(mpsProject).removeTransientBoundModule(treeInRepository, nodeTreeNode); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RepositoryGroup_ActionGroup.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RepositoryGroup_ActionGroup.java new file mode 100644 index 00000000..3c1e2d51 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/RepositoryGroup_ActionGroup.java @@ -0,0 +1,20 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.plugins.actions.GeneratedActionGroup; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.workbench.action.ApplicationPlugin; + +public class RepositoryGroup_ActionGroup extends GeneratedActionGroup { + public static final String ID = "org.modelix.model.mpsplugin.plugin.RepositoryGroup_ActionGroup"; + + public RepositoryGroup_ActionGroup(@NotNull ApplicationPlugin plugin) { + super("RepositoryGroup", ID, plugin); + setIsInternal(false); + setPopup(false); + RepositoryGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.LoadHistoryForRepository_Action"); + RepositoryGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.RemoveRepository_Action"); + RepositoryGroup_ActionGroup.this.addAction("org.modelix.model.mpsplugin.plugin.GetCloudRepositorySize_Action"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/SetProperty_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/SetProperty_Action.java new file mode 100644 index 00000000..b53131ae --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/SetProperty_Action.java @@ -0,0 +1,118 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import org.modelix.model.api.INode; +import org.jetbrains.mps.openapi.language.SProperty; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNodeBinding; +import kotlin.jvm.functions.Function0; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.InputValidator; +import org.modelix.model.area.PArea; +import kotlin.Unit; + +public class SetProperty_Action extends BaseAction { + private static final Icon ICON = null; + + private INode node; + private SProperty role; + public SetProperty_Action(INode node_par, SProperty role_par) { + super("Set Property '...'", "", ICON); + this.node = node_par; + this.role = role_par; + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.NONE); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + event.getPresentation().setText("Set Property '" + SetProperty_Action.this.role.getName() + "' (" + SetProperty_Action.this.role.getOwner().getName() + ")"); + return true; + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + final CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + + String currentValue = CloudNodeTreeNodeBinding.getTreeInRepository(nodeTreeNode).computeRead(new Function0() { + public String invoke() { + return nodeTreeNode.getNode().getPropertyValue(SetProperty_Action.this.role.getName()); + } + }); + final String value = Messages.showInputDialog(event.getData(CommonDataKeys.PROJECT), "Value", "Set Property '" + SetProperty_Action.this.role.getName() + "'", null, currentValue, new InputValidator() { + @Override + public boolean checkInput(String s) { + // TODO perhaps look into the type of the property to authorize it or not + return true; + } + + @Override + public boolean canClose(String s) { + return true; + } + }); + if (value == null) { + return; + } + + new PArea(nodeTreeNode.getBranch()).executeWrite(new Function0() { + public Unit invoke() { + SetProperty_Action.this.node.setPropertyValue(SetProperty_Action.this.role.getName(), value); + return Unit.INSTANCE; + } + }); + } + @NotNull + public String getActionId() { + StringBuilder res = new StringBuilder(); + res.append(super.getActionId()); + res.append("#"); + res.append(node_State((INode) this.node)); + res.append("!"); + res.append(role_State((SProperty) this.role)); + res.append("!"); + return res.toString(); + } + public static String node_State(INode object) { + return object.toString(); + } + public static String role_State(SProperty object) { + return object.getName(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowAuthenticationInfo_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowAuthenticationInfo_Action.java new file mode 100644 index 00000000..6d215683 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowAuthenticationInfo_Action.java @@ -0,0 +1,64 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.history.ModelServerTreeNode; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import com.intellij.openapi.ui.Messages; + +public class ShowAuthenticationInfo_Action extends BaseAction { + private static final Icon ICON = null; + + public ShowAuthenticationInfo_Action() { + super("Show Authentication Info", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return event.getData(MPSCommonDataKeys.TREE_NODE) instanceof ModelServerTreeNode; + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + ModelServerConnection modelServer = ((ModelServerTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)).getModelServer(); + String author = modelServer.getAuthor(); + String email = modelServer.getEmail(); + Messages.showInfoMessage(event.getData(CommonDataKeys.PROJECT), "Author: " + author + "\nEmail: " + email, "Authentication Info"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowProperties_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowProperties_Action.java new file mode 100644 index 00000000..2c819708 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowProperties_Action.java @@ -0,0 +1,90 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNodeBinding; +import org.modelix.model.api.INode; +import java.util.List; +import org.modelix.model.api.IProperty; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import com.intellij.openapi.ui.Messages; + +public class ShowProperties_Action extends BaseAction { + private static final Icon ICON = null; + + public ShowProperties_Action() { + super("Show Properties", "", ICON); + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.NONE); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isProperNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + final CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + CloudRepository treeInRepository = CloudNodeTreeNodeBinding.getTreeInRepository(nodeTreeNode); + // I need to know in which module to look for this node + + final StringBuilder sb = new StringBuilder(); + treeInRepository.runRead(new Runnable() { + public void run() { + INode node = nodeTreeNode.getNode(); + List properties = node.getConcept().getAllProperties(); + for (String property : ListSequence.fromList(properties).select(new ISelector() { + public String select(IProperty it) { + return it.getName(); + } + }).concat(ListSequence.fromList(node.getPropertyRoles())).distinct()) { + sb.append(property); + sb.append(" = "); + sb.append(node.getPropertyValue(property)); + sb.append("\n"); + } + } + }); + Messages.showMessageDialog(event.getData(CommonDataKeys.PROJECT), sb.toString(), "Properties", null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowReferences_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowReferences_Action.java new file mode 100644 index 00000000..ddf9d18a --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/ShowReferences_Action.java @@ -0,0 +1,102 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNodeBinding; +import org.modelix.model.api.INode; +import java.util.List; +import org.modelix.model.api.IReferenceLink; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import org.modelix.model.api.PNodeAdapter; +import java.util.Objects; +import com.intellij.openapi.ui.Messages; + +public class ShowReferences_Action extends BaseAction { + private static final Icon ICON = null; + + public ShowReferences_Action() { + super("Show References", "", ICON); + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.NONE); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isProperNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + final CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + CloudRepository treeInRepository = CloudNodeTreeNodeBinding.getTreeInRepository(nodeTreeNode); + // I need to know in which module to look for this node + + final StringBuilder sb = new StringBuilder(); + treeInRepository.runRead(new Runnable() { + public void run() { + INode node = nodeTreeNode.getNode(); + List referenceLinks = node.getConcept().getAllReferenceLinks(); + for (String refLink : ListSequence.fromList(referenceLinks).select(new ISelector() { + public String select(IReferenceLink it) { + return it.getName(); + } + }).concat(ListSequence.fromList(node.getReferenceRoles())).distinct()) { + sb.append(refLink); + sb.append(" -> "); + INode target = node.getReferenceTarget(refLink); + if (target instanceof PNodeAdapter) { + PNodeAdapter targetAsPNA = ((PNodeAdapter) target); + if (!(Objects.equals(targetAsPNA.getBranch(), nodeTreeNode.getBranch()))) { + sb.append("[branch " + targetAsPNA.getBranch().getId() + "] "); + } + sb.append("#"); + sb.append(Long.toHexString(targetAsPNA.getNodeId())); + } else { + sb.append(target); + } + sb.append("\n"); + } + } + }); + Messages.showMessageDialog(event.getData(CommonDataKeys.PROJECT), sb.toString(), "References", null); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/StoreAllModules_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/StoreAllModules_Action.java new file mode 100644 index 00000000..a1b5bb72 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/StoreAllModules_Action.java @@ -0,0 +1,174 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.TreeNodeClassification; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.project.MPSProject; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.history.CloudNodeTreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.mpsplugin.history.ModelServerTreeNode; +import org.modelix.model.lazy.RepositoryId; +import org.modelix.model.mpsplugin.history.RepositoryTreeNode; +import org.modelix.model.mpsplugin.CloudRepository; +import org.modelix.model.api.PNodeAdapter; +import org.modelix.model.api.IBranch; +import com.intellij.openapi.progress.Task; +import jetbrains.mps.ide.project.ProjectHelper; +import com.intellij.openapi.progress.ProgressIndicator; +import jetbrains.mps.progress.ProgressMonitorAdapter; +import jetbrains.mps.smodel.MPSModuleRepository; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import java.util.List; +import org.jetbrains.mps.openapi.module.SModule; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; +import java.util.Set; +import kotlin.jvm.functions.Function0; +import jetbrains.mps.internal.collections.runtime.ISetSequence; +import org.modelix.model.api.ITransaction; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.internal.collections.runtime.IWhereFilter; +import java.util.Collections; +import kotlin.Unit; +import org.modelix.model.api.IWriteTransaction; +import org.modelix.model.mpsadapters.mps.SConceptAdapter; +import org.modelix.model.mpsplugin.ModelCloudImportUtils; +import com.intellij.openapi.progress.ProgressManager; +import org.jetbrains.mps.openapi.language.SContainmentLink; +import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; +import org.jetbrains.mps.openapi.language.SProperty; +import org.jetbrains.mps.openapi.language.SConcept; + +public class StoreAllModules_Action extends BaseAction { + private static final Icon ICON = null; + + public StoreAllModules_Action() { + super("Store Entire MPS Module Repository", "", ICON); + this.setIsAlwaysVisible(false); + this.setExecuteOutsideCommand(true); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + return TreeNodeClassification.isProjectNode(event.getData(MPSCommonDataKeys.TREE_NODE)); + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + MPSProject p = event.getData(MPSCommonDataKeys.MPS_PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + CloudNodeTreeNode nodeTreeNode = (CloudNodeTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE); + final ModelServerConnection modelServer = nodeTreeNode.getAncestor(ModelServerTreeNode.class).getModelServer(); + RepositoryId repositoryId = nodeTreeNode.getAncestor(RepositoryTreeNode.class).getRepositoryId(); + final CloudRepository treeInRepository = new CloudRepository(modelServer, repositoryId); + final long cloudProjectId = ((PNodeAdapter) nodeTreeNode.getNode()).getNodeId(); + final IBranch branch = treeInRepository.getActiveBranch().getBranch(); + + Task.Backgroundable task = new Task.Backgroundable(ProjectHelper.toIdeaProject(event.getData(MPSCommonDataKeys.MPS_PROJECT)), "Import MPS Repository", true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + final ProgressMonitorAdapter progress = new ProgressMonitorAdapter(indicator); + + final MPSModuleRepository mpsRepo = MPSModuleRepository.getInstance(); + final Wrappers._T> mpsModules = new Wrappers._T>(null); + mpsRepo.getModelAccess().runReadAction(new Runnable() { + public void run() { + mpsModules.value = ListSequence.fromListWithValues(new ArrayList(), mpsRepo.getModules()); + } + }); + + final Set existingModules = branch.computeRead(new Function0>() { + public ISetSequence invoke() { + final ITransaction t = branch.getTransaction(); + Iterable existingModules = t.getChildren(cloudProjectId, LINKS.modules$Bi3g.getName()); + return SetSequence.fromSetWithValues(new HashSet(), Sequence.fromIterable(existingModules).select(new ISelector() { + public String select(Long it) { + return t.getProperty(it, PROPS.name$MnvL.getName()); + } + })); + } + }); + mpsModules.value = ListSequence.fromList(mpsModules.value).where(new IWhereFilter() { + public boolean accept(SModule it) { + return !(SetSequence.fromSet(existingModules).contains(it.getModuleName())); + } + }).toListSequence(); + + Collections.shuffle(mpsModules.value); + progress.start("Importing " + ListSequence.fromList(mpsModules.value).count() + " Modules", ListSequence.fromList(mpsModules.value).count()); + for (final SModule mpsModule : ListSequence.fromList(mpsModules.value)) { + if (progress.isCanceled()) { + break; + } + while (modelServer.getClient().getStoreCache().getKeyValueStore().getPendingSize() > 10000) { + if (progress.isCanceled()) { + break; + } + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + break; + } + } + progress.step("Importing Module " + mpsModule.getModuleName()); + branch.runWrite(new Function0() { + public Unit invoke() { + IWriteTransaction t = branch.getWriteTransaction(); + long cloudModuleId = t.addNewChild(cloudProjectId, LINKS.modules$Bi3g.getName(), -1, SConceptAdapter.wrap(CONCEPTS.Module$4i)); + t.setProperty(cloudModuleId, PROPS.name$MnvL.getName(), mpsModule.getModuleName()); + ModelCloudImportUtils.replicatePhysicalModule(treeInRepository, new PNodeAdapter(cloudModuleId, branch), mpsModule, null, progress.subTask(1)); + return Unit.INSTANCE; + } + }); + } + } + }; + + ProgressManager.getInstance().run(task); + } + + private static final class LINKS { + /*package*/ static final SContainmentLink modules$Bi3g = MetaAdapterFactory.getContainmentLink(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x37a0917d689de959L, 0x37a0917d689de9e2L, "modules"); + } + + private static final class PROPS { + /*package*/ static final SProperty name$MnvL = MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"); + } + + private static final class CONCEPTS { + /*package*/ static final SConcept Module$4i = MetaAdapterFactory.getConcept(0xa7577d1d4e5431dL, 0x98b1fae38f9aee80L, 0x69652614fd1c50fL, "org.modelix.model.repositoryconcepts.structure.Module"); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/SwitchBranch_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/SwitchBranch_Action.java new file mode 100644 index 00000000..f423074e --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/SwitchBranch_Action.java @@ -0,0 +1,53 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.jetbrains.annotations.NotNull; +import org.modelix.model.mpsplugin.history.CloudBranchTreeNode; + +public class SwitchBranch_Action extends BaseAction { + private static final Icon ICON = null; + + public SwitchBranch_Action() { + super("Switch to This Branch", "", ICON); + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + CloudBranchTreeNode branchTreeNode = ((CloudBranchTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)); + branchTreeNode.switchBranch(); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/TextIcon_1.png b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/TextIcon_1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b7e007522cd194bcd91ddb25ce8e589040a71a9 GIT binary patch literal 259 zcmV+e0sQ`nP)&eg2^zP{fR17CboFyt=akR{0PW~Q(EtDd literal 0 HcmV?d00001 diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Unbind_Action.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Unbind_Action.java new file mode 100644 index 00000000..e1a2e51d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/Unbind_Action.java @@ -0,0 +1,74 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import jetbrains.mps.workbench.action.BaseAction; +import javax.swing.Icon; +import jetbrains.mps.workbench.action.ActionAccess; +import com.intellij.openapi.actionSystem.AnActionEvent; +import java.util.Map; +import org.modelix.model.mpsplugin.history.CloudBindingTreeNode; +import jetbrains.mps.ide.actions.MPSCommonDataKeys; +import org.modelix.model.mpsplugin.Binding; +import org.modelix.model.mpsplugin.ModuleBinding; +import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import javax.swing.tree.TreeNode; +import org.modelix.model.mpsplugin.ModelServerConnection; +import org.modelix.model.mpsplugin.CloudRepository; + +public class Unbind_Action extends BaseAction { + private static final Icon ICON = null; + + public Unbind_Action() { + super("Unbind", "", ICON); + this.setIsAlwaysVisible(false); + this.setActionAccess(ActionAccess.UNDO_PROJECT); + } + @Override + public boolean isDumbAware() { + return true; + } + @Override + public boolean isApplicable(AnActionEvent event, final Map _params) { + CloudBindingTreeNode bindingTreeNode = ((CloudBindingTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)); + Binding binding = bindingTreeNode.getBinding(); + // Project binding cannot currently be removed + return binding instanceof ModuleBinding; + } + @Override + public void doUpdate(@NotNull AnActionEvent event, final Map _params) { + this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); + } + @Override + protected boolean collectActionData(AnActionEvent event, final Map _params) { + if (!(super.collectActionData(event, _params))) { + return false; + } + { + Project p = event.getData(CommonDataKeys.PROJECT); + if (p == null) { + return false; + } + } + { + TreeNode p = event.getData(MPSCommonDataKeys.TREE_NODE); + if (p == null) { + return false; + } + } + return true; + } + @Override + public void doExecute(@NotNull final AnActionEvent event, final Map _params) { + CloudBindingTreeNode bindingTreeNode = ((CloudBindingTreeNode) event.getData(MPSCommonDataKeys.TREE_NODE)); + Binding binding = bindingTreeNode.getBinding(); + // Project binding cannot currently be removed + ModuleBinding moduleBinding = ((ModuleBinding) binding); + ModelServerConnection modelServer = bindingTreeNode.getModelServer(); + modelServer.removeBinding(moduleBinding); + CloudRepository repositoryInModelServer = bindingTreeNode.getRepositoryInModelServer(); + PersistedBindingConfiguration.getInstance(event.getData(CommonDataKeys.PROJECT)).removeBoundModule(repositoryInModelServer, moduleBinding); + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/_Adapters.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/_Adapters.java new file mode 100644 index 00000000..ed1e38da --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/_Adapters.java @@ -0,0 +1,18 @@ +package org.modelix.model.mpsplugin.plugin; + +/*Generated by MPS */ + +import java.util.function.Consumer; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; + +public class _Adapters { + public static class _return_P1_E0_to_Consumer_adapter implements Consumer { + private _FunctionTypes._return_P1_E0 adapted; + public _return_P1_E0_to_Consumer_adapter(_FunctionTypes._return_P1_E0 adapted) { + this.adapted = adapted; + } + public void accept(P1 param1) { + this.adapted.invoke(param1); + } + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/trace.info b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/trace.info new file mode 100644 index 00000000..9c70eea1 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/plugin/trace.info @@ -0,0 +1,5686 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/CloudModuleTreeNode.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/CloudModuleTreeNode.java new file mode 100644 index 00000000..0a379bd9 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/CloudModuleTreeNode.java @@ -0,0 +1,92 @@ +package org.modelix.model.mpsplugin.projectview; + +/*Generated by MPS */ + +import jetbrains.mps.ide.ui.tree.module.ProjectModuleTreeNode; +import org.jetbrains.mps.openapi.module.SModuleListenerBase; +import org.jetbrains.mps.openapi.module.SModule; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.model.SModelReference; +import javax.swing.SwingUtilities; +import org.jetbrains.annotations.NotNull; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.ISelector; +import jetbrains.mps.ide.ui.tree.smodel.SModelTreeNode; +import javax.swing.tree.DefaultTreeModel; +import jetbrains.mps.ide.ui.tree.MPSTree; + +public class CloudModuleTreeNode extends ProjectModuleTreeNode { + private boolean myInitialized = false; + private SModuleListenerBase moduleListener = new SModuleListenerBase() { + @Override + public void modelAdded(SModule module, SModel model) { + update(); + } + @Override + public void modelRemoved(SModule module, SModelReference ref) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + update(); + } + }); + } + }; + public CloudModuleTreeNode(@NotNull SModule module) { + super(module); + setNodeIdentifier(module.getModuleId().toString()); + setIcon(CloudProjectViewExtension.MODULE_ICON); + module.addModuleListener(moduleListener); + } + @Override + public String getModuleText() { + return getModule().getModuleName(); + } + @Override + public boolean isInitialized() { + return myInitialized; + } + + @Override + protected void doInit() { + populate(); + myInitialized = true; + } + + protected void populate() { + Iterable models = getModule().getModels(); + for (SModel model : Sequence.fromIterable(models).sort(new ISelector() { + public String select(SModel it) { + return it.getName().getLongName(); + } + }, true)) { + SModelTreeNode tn = new SModelTreeNode(model); + tn.setIcon(CloudProjectViewExtension.MODEL_ICON); + tn.setBaseIcon(CloudProjectViewExtension.MODEL_ICON); + add(tn); + } + check_7wx4yo_a2a8(check_7wx4yo_a0c0i(getTree(), this), this); + } + + @Override + protected void doUpdate() { + super.doUpdate(); + myInitialized = false; + removeAllChildren(); + } + + public void dispose() { + getModule().removeModuleListener(moduleListener); + } + private static void check_7wx4yo_a2a8(DefaultTreeModel checkedDotOperand, CloudModuleTreeNode checkedDotThisExpression) { + if (null != checkedDotOperand) { + checkedDotOperand.nodeStructureChanged(checkedDotThisExpression); + } + + } + private static DefaultTreeModel check_7wx4yo_a0c0i(MPSTree checkedDotOperand, CloudModuleTreeNode checkedDotThisExpression) { + if (null != checkedDotOperand) { + return checkedDotOperand.getModel(); + } + return null; + } +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/CloudProjectViewExtension.java b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/CloudProjectViewExtension.java new file mode 100644 index 00000000..553e4dfa --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/CloudProjectViewExtension.java @@ -0,0 +1,312 @@ +package org.modelix.model.mpsplugin.projectview; + +/*Generated by MPS */ + +import org.apache.log4j.Logger; +import org.apache.log4j.LogManager; +import javax.swing.Icon; +import org.modelix.model.mpsplugin.LetterInSquareIcon; +import java.awt.Color; +import java.util.Map; +import com.intellij.openapi.project.Project; +import jetbrains.mps.internal.collections.runtime.MapSequence; +import java.util.HashMap; +import jetbrains.mps.project.MPSProject; +import jetbrains.mps.ide.project.ProjectHelper; +import jetbrains.mps.ide.ui.tree.TextTreeNode; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeModelEvent; +import org.apache.log4j.Level; +import javax.swing.tree.DefaultTreeModel; +import org.jetbrains.mps.openapi.module.SRepositoryListener; +import org.jetbrains.mps.openapi.module.SRepositoryListenerBase; +import java.util.concurrent.atomic.AtomicBoolean; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.mps.openapi.module.SModule; +import org.modelix.model.mpsplugin.CloudTransientModule; +import org.jetbrains.mps.openapi.module.SModuleReference; +import com.intellij.openapi.application.ApplicationManager; +import org.jetbrains.mps.openapi.module.SModuleListener; +import org.jetbrains.mps.openapi.module.SModuleListenerBase; +import org.jetbrains.mps.openapi.model.SModel; +import org.jetbrains.mps.openapi.model.SModelReference; +import de.q60.mps.util.invalidation.Invalidatable; +import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; +import jetbrains.mps.ide.projectPane.logicalview.ProjectTree; +import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; +import javax.swing.Timer; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import jetbrains.mps.ide.projectPane.ProjectPane; +import jetbrains.mps.ide.ui.tree.MPSTreeNode; +import java.util.Set; +import jetbrains.mps.internal.collections.runtime.SetSequence; +import java.util.HashSet; +import jetbrains.mps.internal.collections.runtime.Sequence; +import jetbrains.mps.internal.collections.runtime.IVisitor; +import jetbrains.mps.internal.collections.runtime.ISelector; +import javax.swing.tree.TreeNode; +import java.util.List; +import jetbrains.mps.internal.collections.runtime.ListSequence; +import java.util.ArrayList; + +public class CloudProjectViewExtension { + private static final Logger LOG = LogManager.getLogger(CloudProjectViewExtension.class); + public static final Icon ROOT_ICON = new LetterInSquareIcon("C", 14, 3.0f, 13.0f, Color.YELLOW, Color.BLACK); + public static final Icon MODULE_ICON = new LetterInSquareIcon("M", 14, 2.0f, 13.0f, Color.YELLOW, Color.BLACK); + public static final Icon MODEL_ICON = new LetterInSquareIcon("m", 14, 2.0f, 12.0f, Color.YELLOW, Color.BLACK); + + private static Map ourInstances = MapSequence.fromMap(new HashMap()); + + public static CloudProjectViewExtension getInstance(Project ideaProject) { + CloudProjectViewExtension instance = MapSequence.fromMap(ourInstances).get(ideaProject); + if (instance == null) { + MPSProject mpsProject = ProjectHelper.fromIdeaProject(ideaProject); + instance = new CloudProjectViewExtension(mpsProject); + MapSequence.fromMap(ourInstances).put(ideaProject, instance); + } + return instance; + } + public static CloudProjectViewExtension getInstance(jetbrains.mps.project.Project mpsProject) { + return getInstance(ProjectHelper.toIdeaProject(mpsProject)); + } + + private jetbrains.mps.project.Project project; + private TextTreeNode cloudTreeNode; + private TreeModelListener treeListener = new TreeModelListener() { + private boolean handling; + public void treeNodesChanged(TreeModelEvent p0) { + handle(); + } + public void treeNodesInserted(TreeModelEvent p0) { + handle(); + } + public void treeNodesRemoved(TreeModelEvent p0) { + handle(); + } + public void treeStructureChanged(TreeModelEvent p0) { + handle(); + } + public void handle() { + if (handling) { + return; + } + try { + handling = true; + attachCloudRootIfNotEmpty(); + } catch (Exception ex) { + if (LOG.isEnabledFor(Level.ERROR)) { + LOG.error("", ex); + } + } finally { + handling = false; + } + } + }; + private DefaultTreeModel treeModel; + + private SRepositoryListener repositoryListener = new SRepositoryListenerBase() { + private AtomicBoolean modulesDirty = new AtomicBoolean(true); + public void moduleAdded(@NotNull SModule m) { + if (m instanceof CloudTransientModule) { + m.addModuleListener(moduleListener); + queueUpdate(); + } + } + public void moduleRemoved(@NotNull SModuleReference m) { + queueUpdate(); + } + public void queueUpdate() { + modulesDirty.set(true); + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + if (modulesDirty.getAndSet(false)) { + updateModules(); + } + } + }); + } + }; + private SModuleListener moduleListener = new SModuleListenerBase() { + @Override + public void modelAdded(SModule module, SModel model) { + super.modelAdded(module, model); + } + @Override + public void modelRemoved(SModule module, SModelReference ref) { + super.modelRemoved(module, ref); + } + }; + private Invalidatable invalidatable = new Invalidatable("Project view extension", new _FunctionTypes._void_P0_E0() { + public void invoke() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + forceUpdate(); + } + }); + } + }) { + @Override + public String getText() { + return "Project view extension (" + project.getName() + ")"; + } + }; + + public CloudProjectViewExtension(jetbrains.mps.project.Project project) { + this.project = project; + } + + public void init() { + cloudTreeNode = new TextTreeNode("Cloud"); + cloudTreeNode.setIcon(ROOT_ICON); + waitForProjectTree(new _FunctionTypes._void_P1_E0() { + public void invoke(ProjectTree tree) { + treeModel = tree.getModel(); + treeModel.addTreeModelListener(treeListener); + project.getRepository().addRepositoryListener(repositoryListener); + updateModules(); + } + }); + } + + private void waitForProjectTree(final _FunctionTypes._void_P1_E0 callback) { + ProjectTree tree = getProjectTree(); + if (tree != null) { + callback.invoke(tree); + } else { + final Wrappers._T timer = new Wrappers._T(null); + timer.value = new Timer(1000, new ActionListener() { + public void actionPerformed(ActionEvent e) { + ProjectTree tree = getProjectTree(); + if (tree != null) { + callback.invoke(tree); + timer.value.stop(); + } + } + }); + timer.value.start(); + } + } + + private ProjectTree getProjectTree() { + if (project.isDisposed()) { + return null; + } + ProjectPane pane = ProjectPane.getInstance(project); + if (pane == null) { + return null; + } + return pane.getTree(); + } + + public void dispose() { + project.getRepository().removeRepositoryListener(repositoryListener); + if (treeModel != null) { + treeModel.removeTreeModelListener(treeListener); + } + MapSequence.fromMap(ourInstances).removeKey(ProjectHelper.toIdeaProject(project)); + invalidatable.dispose(); + } + + public void attachCloudRoot() { + ProjectPane projectPane = ProjectPane.getInstance(project); + final MPSTreeNode root = projectPane.getTree().getRootNode(); + if (root == null) { + return; + } + final DefaultTreeModel model = projectPane.getTree().getModel(); + + // wrong parent + if (cloudTreeNode.getParent() != null && cloudTreeNode.getParent() != root) { + cloudTreeNode.removeFromParent(); + } + + // wrong position + final int preferedIndex = 3; + if (cloudTreeNode.getParent() != null && cloudTreeNode.getParent().getIndex(cloudTreeNode) != Math.min(cloudTreeNode.getParent().getChildCount() - 1, preferedIndex)) { + model.removeNodeFromParent(cloudTreeNode); + } + + if (cloudTreeNode.getParent() == null) { + project.getRepository().getModelAccess().runReadAction(new Runnable() { + public void run() { + model.insertNodeInto(cloudTreeNode, root, Math.min(root.getChildCount(), preferedIndex)); + } + }); + } + } + + public void attachCloudRootIfNotEmpty() { + if (cloudTreeNode.getChildCount() == 0) { + if (cloudTreeNode.getParent() != null && cloudTreeNode.getTree() != null) { + cloudTreeNode.getTree().getModel().removeNodeFromParent(cloudTreeNode); + } + } else { + attachCloudRoot(); + } + } + + public void forceUpdate() { + while (cloudTreeNode.getChildCount() > 0) { + CloudModuleTreeNode moduleTreeNode = (CloudModuleTreeNode) cloudTreeNode.getChildAt(0); + getProjectTree().getModel().removeNodeFromParent(moduleTreeNode); + moduleTreeNode.dispose(); + } + updateModules(); + } + + public void updateModules() { + final MPSTreeNode root = getProjectTree().getRootNode(); + if (root == null) { + return; + } + final DefaultTreeModel treeModel = getProjectTree().getModel(); + + project.getRepository().getModelAccess().runReadAction(new Runnable() { + public void run() { + Iterable modules = project.getRepository().getModules(); + final Map module2treeNode = MapSequence.fromMap(new HashMap()); + final Set treeNodesToRemove = SetSequence.fromSet(new HashSet()); + Sequence.fromIterable(getChildren(cloudTreeNode)).ofType(CloudModuleTreeNode.class).visitAll(new IVisitor() { + public void visit(CloudModuleTreeNode it) { + SetSequence.fromSet(treeNodesToRemove).addElement(it); + MapSequence.fromMap(module2treeNode).put(it.getModule(), it); + } + }); + int insertAt = 0; + for (CloudTransientModule webModule : Sequence.fromIterable(modules).ofType(CloudTransientModule.class).sort(new ISelector() { + public String select(CloudTransientModule it) { + return it.getModuleName(); + } + }, true)) { + CloudModuleTreeNode moduleTreeNode = MapSequence.fromMap(module2treeNode).get(webModule); + if (moduleTreeNode == null) { + treeModel.insertNodeInto(new CloudModuleTreeNode(webModule), cloudTreeNode, insertAt); + insertAt++; + } else { + insertAt = moduleTreeNode.getParent().getIndex(moduleTreeNode) + 1; + MapSequence.fromMap(module2treeNode).removeKey(webModule); + SetSequence.fromSet(treeNodesToRemove).removeElement(moduleTreeNode); + } + } + SetSequence.fromSet(treeNodesToRemove).visitAll(new IVisitor() { + public void visit(CloudModuleTreeNode it) { + treeModel.removeNodeFromParent(it); + it.dispose(); + } + }); + attachCloudRootIfNotEmpty(); + } + }); + } + + private static Iterable getChildren(TreeNode parent) { + List result = ListSequence.fromList(new ArrayList()); + for (int i = 0; i < parent.getChildCount(); i++) { + ListSequence.fromList(result).addElement(parent.getChildAt(i)); + } + return result; + } + + +} diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/trace.info b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/trace.info new file mode 100644 index 00000000..57f15a89 --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/projectview/trace.info @@ -0,0 +1,483 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/trace.info b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/trace.info new file mode 100644 index 00000000..d5e1ae7d --- /dev/null +++ b/mps-legacy-sync-plugin/src/main/java/org/modelix/model/mpsplugin/trace.info @@ -0,0 +1,8753 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +