You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by st...@apache.org on 2021/01/13 03:56:16 UTC
[openwhisk-intellij-plugin] branch master updated: Initial import
of openwhisk-intellij-plugin donation from NAVER (#5)
This is an automated email from the ASF dual-hosted git repository.
style95 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openwhisk-intellij-plugin.git
The following commit(s) were added to refs/heads/master by this push:
new ec86984 Initial import of openwhisk-intellij-plugin donation from NAVER (#5)
ec86984 is described below
commit ec869843d97601a152c3cc191d10bfbf23408f2d
Author: 김건희 <ki...@gmail.com>
AuthorDate: Wed Jan 13 12:55:52 2021 +0900
Initial import of openwhisk-intellij-plugin donation from NAVER (#5)
---
.gitignore | 6 +
LICENSE | 203 +++++++++
README.md | 53 +++
build.gradle | 61 +++
config/checkstyle/checkstyle.xml | 202 +++++++++
gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 56172 bytes
gradle/wrapper/gradle-wrapper.properties | 19 +
gradlew | 186 +++++++++
gradlew.bat | 98 +++++
settings.gradle | 18 +
.../intellij/common/DialogWrapperWithApply.java | 71 ++++
.../navercorp/openwhisk/intellij/common/Icons.java | 72 ++++
.../common/error/NotExistFileException.java | 25 ++
.../common/notification/SimpleNotifier.java | 51 +++
.../intellij/common/service/WhiskService.java | 57 +++
.../intellij/common/service/WskDeployService.java | 66 +++
.../intellij/common/utils/CommandUtils.java | 60 +++
.../intellij/common/utils/EventUtils.java | 57 +++
.../openwhisk/intellij/common/utils/FileUtils.java | 88 ++++
.../intellij/common/utils/JsonParserUtils.java | 214 ++++++++++
.../intellij/common/utils/ParameterUtils.java | 66 +++
.../intellij/common/utils/ParametricRunnable.java | 25 ++
.../intellij/common/utils/ValidationUtils.java | 52 +++
.../intellij/common/utils/WhiskUtils.java | 62 +++
.../intellij/common/whisk/model/Binding.java | 60 +++
.../intellij/common/whisk/model/Limits.java | 88 ++++
.../intellij/common/whisk/model/Runtime.java | 188 +++++++++
.../intellij/common/whisk/model/WhiskAuth.java | 54 +++
.../common/whisk/model/WhiskAuthWithName.java | 48 +++
.../intellij/common/whisk/model/WhiskEndpoint.java | 69 +++
.../common/whisk/model/WhiskNamespace.java | 113 +++++
.../whisk/model/action/CompactWhiskAction.java | 136 ++++++
.../whisk/model/action/ExecutableWhiskAction.java | 67 +++
.../common/whisk/model/action/WhiskAction.java | 292 +++++++++++++
.../whisk/model/action/WhiskActionMetaData.java | 46 ++
.../whisk/model/activation/WhiskActivation.java | 183 ++++++++
.../model/activation/WhiskActivationMetaData.java | 75 ++++
.../model/activation/WhiskActivationWithLogs.java | 90 ++++
.../intellij/common/whisk/model/exec/CodeExec.java | 121 ++++++
.../whisk/model/exec/CodeExecSerializer.java | 63 +++
.../intellij/common/whisk/model/exec/Exec.java | 52 +++
.../common/whisk/model/exec/ExecMetaData.java | 26 ++
.../common/whisk/model/pkg/WhiskPackage.java | 137 ++++++
.../whisk/model/pkg/WhiskPackageWithActions.java | 92 ++++
.../model/trigger/ExecutableWhiskTrigger.java | 93 +++++
.../model/trigger/SimplifiedEntityMetaData.java | 72 ++++
.../whisk/model/trigger/SimplifiedWhiskRule.java | 65 +++
.../common/whisk/model/trigger/WhiskRule.java | 71 ++++
.../whisk/model/trigger/WhiskRuleMetaData.java | 126 ++++++
.../common/whisk/model/trigger/WhiskTrigger.java | 117 ++++++
.../whisk/model/trigger/WhiskTriggerMetaData.java | 37 ++
.../whisk/model/trigger/WhiskTriggerRoot.java | 20 +
.../whisk/model/wskdeploy/NullWskDeployBinary.java | 21 +
.../whisk/model/wskdeploy/WskDeployBinary.java | 43 ++
.../common/whisk/model/wskdeploy/WskDeployCmd.java | 31 ++
.../whisk/model/wskdeploy/WskDeployCmdDeploy.java | 74 ++++
.../model/wskdeploy/WskDeployCmdResponse.java | 53 +++
.../model/wskdeploy/WskDeployCmdUndeploy.java | 74 ++++
.../whisk/model/wskdeploy/WskDeployFile.java | 20 +
.../whisk/model/wskdeploy/WskDeployManifest.java | 77 ++++
.../common/whisk/service/WhiskActionService.java | 128 ++++++
.../whisk/service/WhiskActivationService.java | 70 ++++
.../whisk/service/WhiskNamespaceService.java | 65 +++
.../common/whisk/service/WhiskPackageService.java | 140 +++++++
.../common/whisk/service/WhiskRuleService.java | 72 ++++
.../common/whisk/service/WhiskTriggerService.java | 129 ++++++
.../dialog/action/ActionManagerDialog.java | 67 +++
.../explorer/dialog/action/DeleteActionDialog.java | 46 ++
.../dialog/action/listener/DownActionListener.java | 21 +
.../action/listener/RemoveActionListener.java | 21 +
.../dialog/action/listener/UpActionListener.java | 21 +
.../dialog/action/ui/ActionManagerDialogForm.form | 328 +++++++++++++++
.../dialog/action/ui/ActionManagerDialogForm.java | 413 ++++++++++++++++++
.../explorer/dialog/action/ui/CodeTypeForm.form | 39 ++
.../explorer/dialog/action/ui/CodeTypeForm.java | 85 ++++
.../dialog/action/ui/DefaultParameterForm.form | 46 ++
.../dialog/action/ui/DefaultParameterForm.java | 40 ++
.../explorer/dialog/action/ui/DockerImageForm.form | 39 ++
.../explorer/dialog/action/ui/DockerImageForm.java | 40 ++
.../dialog/action/ui/LinkedActionsEntryForm.form | 61 +++
.../dialog/action/ui/LinkedActionsEntryForm.java | 98 +++++
.../dialog/action/ui/LinkedActionsForm.form | 87 ++++
.../dialog/action/ui/LinkedActionsForm.java | 180 ++++++++
.../dialog/endpoint/AddEndpointDialog.java | 63 +++
.../dialog/endpoint/DeleteEndpointDialog.java | 50 +++
.../dialog/endpoint/EditEndpointDialog.java | 64 +++
.../dialog/endpoint/ui/AddEndpointDialogForm.form | 97 +++++
.../dialog/endpoint/ui/AddEndpointDialogForm.java | 102 +++++
.../dialog/endpoint/ui/EditEndpointDialogForm.form | 97 +++++
.../dialog/endpoint/ui/EditEndpointDialogForm.java | 115 +++++
.../dialog/namespace/AddNamespaceDialog.java | 64 +++
.../dialog/namespace/DeleteNamespaceDialog.java | 50 +++
.../dialog/namespace/EditNamespaceDialog.java | 65 +++
.../namespace/ui/AddNamespaceDialogForm.form | 97 +++++
.../namespace/ui/AddNamespaceDialogForm.java | 145 +++++++
.../namespace/ui/EditNamespaceDialogForm.form | 175 ++++++++
.../namespace/ui/EditNamespaceDialogForm.java | 156 +++++++
.../explorer/dialog/pkg/DeletePackageDialog.java | 66 +++
.../dialog/pkg/PackageCreationManagerDialog.java | 64 +++
.../explorer/dialog/pkg/PackageManagerDialog.java | 65 +++
.../pkg/ui/PackageCreationManagerDialogForm.form | 59 +++
.../pkg/ui/PackageCreationManagerDialogForm.java | 75 ++++
.../dialog/pkg/ui/PackageManagerDialogForm.form | 287 +++++++++++++
.../dialog/pkg/ui/PackageManagerDialogForm.java | 131 ++++++
.../dialog/trigger/DeleteTriggerDialog.java | 50 +++
.../trigger/TriggerCreationManagerDialog.java | 64 +++
.../dialog/trigger/TriggerManagerDialog.java | 67 +++
.../trigger/listener/RemoveLinkedRuleListener.java | 22 +
.../dialog/trigger/ui/LinkedActionsForm.form | 53 +++
.../dialog/trigger/ui/LinkedActionsForm.java | 62 +++
.../ui/TriggerCreationManagerDialogForm.form | 104 +++++
.../ui/TriggerCreationManagerDialogForm.java | 113 +++++
.../trigger/ui/TriggerManagerDialogForm.form | 215 ++++++++++
.../trigger/ui/TriggerManagerDialogForm.java | 247 +++++++++++
.../explorer/editor/ActivationViewEditor.java | 191 +++++++++
.../editor/ActivationViewEditorProvider.java | 54 +++
.../explorer/editor/ActivationViewVirtualFile.java | 147 +++++++
.../editor/ActivationViewVirtualFileSystem.java | 114 +++++
.../explorer/editor/model/ComboBoxEntityEntry.java | 80 ++++
.../explorer/editor/model/ComboBoxEntityType.java | 21 +
.../editor/ui/ActivationViewEditorForm.form | 85 ++++
.../editor/ui/ActivationViewEditorForm.java | 276 ++++++++++++
.../toolwindow/WhiskExplorerWindowFactory.java | 153 +++++++
.../toolwindow/action/AddEndpointAction.java | 43 ++
.../toolwindow/action/AddNamespaceAction.java | 48 +++
.../toolwindow/action/CreatePackageAction.java | 49 +++
.../toolwindow/action/CreateTriggerAction.java | 49 +++
.../toolwindow/action/DeleteActionAction.java | 71 ++++
.../toolwindow/action/DeleteEndpointAction.java | 97 +++++
.../toolwindow/action/DeleteNamespaceAction.java | 104 +++++
.../toolwindow/action/DeletePackageAction.java | 129 ++++++
.../toolwindow/action/DeleteTriggerAction.java | 70 ++++
.../toolwindow/action/EditActionAction.java | 73 ++++
.../toolwindow/action/EditEndpointAction.java | 44 ++
.../toolwindow/action/EditNamespaceAction.java | 52 +++
.../toolwindow/action/EditPackageAction.java | 67 +++
.../toolwindow/action/EditTriggerAction.java | 82 ++++
.../action/OpenActivationViewAction.java | 66 +++
.../action/OpenAndFireTriggerAction.java | 66 +++
.../toolwindow/action/OpenAndRunActionAction.java | 72 ++++
.../toolwindow/action/RefreshTreeAction.java | 40 ++
.../toolwindow/actiongroup/WhiskActionGroup.java | 39 ++
.../toolwindow/actiongroup/WhiskEndpointGroup.java | 32 ++
.../actiongroup/WhiskNamespaceGroup.java | 39 ++
.../toolwindow/actiongroup/WhiskPackageGroup.java | 31 ++
.../toolwindow/actiongroup/WhiskTriggerGroup.java | 39 ++
.../actiongroup/WhiskTriggerRootGroup.java | 28 ++
.../listener/OpenActionControlActionListener.java | 31 ++
.../listener/OpenTriggerControlActionListener.java | 31 ++
.../listener/RefreshWhiskTreeListener.java | 27 ++
.../explorer/toolwindow/tree/WhiskTree.java | 178 ++++++++
.../toolwindow/tree/WhiskTreeCellRenderer.java | 74 ++++
.../toolwindow/ui/WhiskExplorerWindowForm.form | 29 ++
.../toolwindow/ui/WhiskExplorerWindowForm.java | 462 +++++++++++++++++++++
.../run/toolwindow/WhiskRunWindowFactory.java | 173 ++++++++
.../action/OpenActionManagerDialogAction.java | 37 ++
.../toolwindow/action/RefreshMetaDataAction.java | 37 ++
.../run/toolwindow/action/RunActionAction.java | 36 ++
.../listener/OpenActionManagerListener.java | 29 ++
.../OpenAndFireTriggerControlActionListener.java | 31 ++
.../OpenAndRunActionControlActionListener.java | 31 ++
.../listener/RefreshActionOrTriggerListener.java | 29 ++
.../run/toolwindow/listener/RunActionListener.java | 28 ++
.../run/toolwindow/ui/WhiskRunWindowForm.form | 73 ++++
.../run/toolwindow/ui/WhiskRunWindowForm.java | 281 +++++++++++++
.../wskdeploy/dialog/WskDeployCmdDialog.java | 67 +++
.../wskdeploy/dialog/WskDeployTempleteDialog.java | 65 +++
.../dialog/ui/WskDeployCmdDialogForm.form | 54 +++
.../dialog/ui/WskDeployCmdDialogForm.java | 100 +++++
.../toolwindow/WskDeployWindowFactory.java | 40 ++
.../action/ChooseWskDeployBinAction.java | 59 +++
.../action/CreateManifestTemplateAction.java | 90 ++++
.../toolwindow/action/RefreshWskDeployAction.java | 40 ++
.../listener/ChooseWskDeployBinaryListener.java | 28 ++
.../listener/RefreshWskDeployManifestListener.java | 27 ++
.../toolwindow/tree/WskDeployTreeCellRenderer.java | 59 +++
.../toolwindow/tree/WskDeployTreeModel.java | 106 +++++
.../toolwindow/ui/WskDeployWindowForm.form | 45 ++
.../toolwindow/ui/WskDeployWindowForm.java | 213 ++++++++++
src/main/resources/META-INF/plugin.xml | 121 ++++++
src/main/resources/icons/arrowDown.svg | 1 +
src/main/resources/icons/arrowUp.svg | 1 +
src/main/resources/icons/event.svg | 1 +
src/main/resources/icons/eventGroup.svg | 1 +
.../icons/language/docker/DockerCompose.svg | 1 +
src/main/resources/icons/language/go/go.svg | 27 ++
.../resources/icons/language/go/go_template.svg | 1 +
.../icons/language/go/go_template_dark.svg | 1 +
src/main/resources/icons/language/java/java 2.svg | 1 +
src/main/resources/icons/language/java/java.svg | 1 +
.../icons/language/javascript/javascript.svg | 1 +
.../resources/icons/language/javascript/js.svg | 1 +
.../resources/icons/language/javascript/nodejs.svg | 1 +
.../icons/language/php/localPHP_interpreter.svg | 1 +
src/main/resources/icons/language/php/php-icon.svg | 1 +
src/main/resources/icons/language/php/php.svg | 28 ++
src/main/resources/icons/language/python/py.svg | 26 ++
.../resources/icons/language/python/python.svg | 1 +
.../resources/icons/language/python/pythonFile.svg | 1 +
src/main/resources/icons/language/ruby/rb.svg | 28 ++
src/main/resources/icons/language/ruby/ruby.svg | 1 +
.../resources/icons/language/ruby/ruby_file.svg | 1 +
src/main/resources/icons/language/ruby/rxml.svg | 1 +
.../resources/icons/language/swift/SwiftLang.svg | 1 +
src/main/resources/icons/language/swift/sw.svg | 27 ++
src/main/resources/icons/openDiskHover.svg | 1 +
src/main/resources/icons/run_anything.svg | 1 +
src/main/resources/icons/seq.svg | 30 ++
src/main/resources/icons/sh.svg | 27 ++
src/main/resources/icons/ssh.svg | 1 +
src/main/resources/icons/yaml.svg | 1 +
src/main/resources/template/HOW-TO-DEPLOY.md | 75 ++++
src/main/resources/template/manifest.yaml | 46 ++
src/main/resources/template/src/index.js | 7 +
src/main/resources/template/src/index.test.js | 12 +
src/main/resources/template/src/package.json | 18 +
.../utils/json/EmptyJsonParserUtilsTests.java | 225 ++++++++++
.../common/utils/whisk/WhiskUtilsTest.java | 34 ++
.../common/whisk/model/WhiskActionJsonTest.java | 239 +++++++++++
.../common/whisk/model/WhiskActionTest.java | 220 ++++++++++
.../common/whisk/model/WhiskActivationTest.java | 124 ++++++
.../intellij/common/whisk/model/WhiskAuthTest.java | 47 +++
.../common/whisk/model/WhiskEndpointTest.java | 60 +++
.../common/whisk/model/WhiskPackageJsonTest.java | 85 ++++
.../common/whisk/model/WhiskPackageTest.java | 90 ++++
.../common/whisk/model/WhiskTriggerJsonTest.java | 75 ++++
.../openwhisk/intellij/utils/AnnotationHelper.java | 115 +++++
.../openwhisk/intellij/utils/FileHelper.java | 22 +
src/test/resources/action.json | 34 ++
src/test/resources/actions.json | 148 +++++++
src/test/resources/activation_with_log.json | 55 +++
src/test/resources/activations.json | 86 ++++
src/test/resources/binary-action.json | 34 ++
src/test/resources/blackbox-action.json | 34 ++
src/test/resources/java-action.json | 35 ++
src/test/resources/package.json | 57 +++
src/test/resources/packages.json | 54 +++
src/test/resources/sequence-action.json | 35 ++
src/test/resources/trigger.json | 24 ++
src/test/resources/triggers.json | 36 ++
240 files changed, 17751 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..312b385
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+gradle.properties
+.idea
+.gradle
+build
+out
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..809ba07
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,203 @@
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2020-present NAVER Corp.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f59a67a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,53 @@
+# OpenWhisk Intellij Plugin
+**OpenWhisk-intellij-support** is an open source Intellij Plugin for [Apache OpenWhisk](https://github.com/apache/openwhisk). It assists users to develop/deploy/manage OpenWhisk functions in Intellij.
+
+## Prerequisites
+Install the dependencies below to use full features:
+* Intellij >= 2018.1.8
+* [wskdeploy](https://github.com/apache/openwhisk-wskdeploy/releases)
+
+This extension finds the `.wskprops` configuration file located in the home path and connects to the Openwhisk server automatically. Set up your configuration referred to the [cli docs](https://github.com/apache/openwhisk/blob/master/docs/cli.md#openwhisk-cli).
+
+## Feature
+### OpenWhisk Explorer
+* Explore all entities in your endpoints/namespaces.
+ * The `.wskprops` file is automatically registered.
+ * You can add the API host manually.
+ * You can add namespace manually by API auth key.
+* Show the action code with syntax highlighting.
+* [Soon] Edit the action code on the remote server.
+* Invoke the action remotely and get the activation result.
+* Show a list of actions related to the sequence action.
+* Show information about the trigger and related rules.
+* Show activations related to the action (Same as `wsk activation list <action>`).
+* Show detailed information of the activation (Same `as wsk activation get <activation_id>`).
+* Update parameters of the action, package, and trigger.
+
+### Manifest View
+* List up manifest YAML files in the workspace.
+* Deploy/Undeploy OpenWhisk packages with manifest (via wskdeploy).
+ * Deploy with the deployment file.
+ * Deploy with multiple credentials.
+
+## How to debug in your local
+```bash
+./gradlew runIde
+```
+
+## License
+
+```
+Copyright 2020-present NAVER Corp.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+```
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..c823c69
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,61 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+ id 'java'
+ id 'org.jetbrains.intellij' version '0.4.18'
+ id 'checkstyle'
+}
+
+group 'com.navercorp.openwhisk.intellij'
+version '1.1.4'
+
+sourceCompatibility = 11
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.8'
+ testImplementation group: 'junit', name: 'junit', version: '4.12'
+}
+
+intellij {
+ version '2020.1.2'
+}
+
+patchPluginXml {
+ sinceBuild '181.*'
+ untilBuild '203.*'
+}
+
+publishPlugin {
+ token = System.getenv("ORG_GRADLE_PROJECT_intellijPublishToken")
+ channels 'beta'
+}
+
+checkstyle {
+ configFile = file("${rootDir}/config/checkstyle/checkstyle.xml")
+ toolVersion = 8.35
+}
+
+tasks.withType(Checkstyle) {
+ reports {
+ xml.enabled false
+ html.enabled true
+ }
+}
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
new file mode 100644
index 0000000..51b20b3
--- /dev/null
+++ b/config/checkstyle/checkstyle.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+ "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
+ "https://checkstyle.org/dtds/configuration_1_3.dtd">
+
+<!--
+ Checkstyle configuration that checks the sun coding conventions from:
+ - the Java Language Specification at
+ https://docs.oracle.com/javase/specs/jls/se11/html/index.html
+ - the Sun Code Conventions at https://www.oracle.com/java/technologies/javase/codeconventions-contents.html
+ - the Javadoc guidelines at
+ https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html
+ - the JDK Api documentation https://docs.oracle.com/en/java/javase/11/
+ - some best practices
+ Checkstyle is very configurable. Be sure to read the documentation at
+ https://checkstyle.org (or in your downloaded distribution).
+ Most Checks are configurable, be sure to consult the documentation.
+ To completely disable a check, just comment it out or delete it from the file.
+ To suppress certain violations please review suppression filters.
+ Finally, it is worth reading the documentation.
+-->
+
+<module name="Checker">
+ <!--
+ If you set the basedir property below, then all reported file
+ names will be relative to the specified directory. See
+ https://checkstyle.org/config.html#Checker
+ <property name="basedir" value="${basedir}"/>
+ -->
+ <property name="severity" value="error"/>
+
+ <property name="fileExtensions" value="java, properties, xml"/>
+
+ <!-- Excludes all 'module-info.java' files -->
+ <!-- See https://checkstyle.org/config_filefilters.html -->
+ <module name="BeforeExecutionExclusionFileFilter">
+ <property name="fileNamePattern" value="module\-info\.java$"/>
+ </module>
+
+ <!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
+ <module name="SuppressionFilter">
+ <property name="file" value="${org.checkstyle.sun.suppressionfilter.config}"
+ default="checkstyle-suppressions.xml" />
+ <property name="optional" value="true"/>
+ </module>
+
+ <!-- Checks that a package-info.java file exists for each package. -->
+ <!-- See https://checkstyle.org/config_javadoc.html#JavadocPackage -->
+ <!--<module name="JavadocPackage"/>-->
+
+ <!-- Checks whether files end with a new line. -->
+ <!-- See https://checkstyle.org/config_misc.html#NewlineAtEndOfFile -->
+ <module name="NewlineAtEndOfFile"/>
+
+ <!-- Checks that property files contain the same keys. -->
+ <!-- See https://checkstyle.org/config_misc.html#Translation -->
+ <module name="Translation"/>
+
+ <!-- Checks for Size Violations. -->
+ <!-- See https://checkstyle.org/config_sizes.html -->
+ <module name="FileLength"/>
+ <module name="LineLength">
+ <property name="fileExtensions" value="java"/>
+ <property name="max" value="160"/>
+ </module>
+
+ <!-- Checks for whitespace -->
+ <!-- See https://checkstyle.org/config_whitespace.html -->
+ <module name="FileTabCharacter"/>
+
+ <!-- Miscellaneous other checks. -->
+ <!-- See https://checkstyle.org/config_misc.html -->
+ <module name="RegexpSingleline">
+ <property name="format" value="\s+$"/>
+ <property name="minimum" value="0"/>
+ <property name="maximum" value="0"/>
+ <property name="message" value="Line has trailing spaces."/>
+ </module>
+
+ <!-- Checks for Headers -->
+ <!-- See https://checkstyle.org/config_header.html -->
+ <!-- <module name="Header"> -->
+ <!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
+ <!-- <property name="fileExtensions" value="java"/> -->
+ <!-- </module> -->
+
+ <module name="TreeWalker">
+
+ <!-- Checks for Javadoc comments. -->
+ <!-- See https://checkstyle.org/config_javadoc.html -->
+ <!--<module name="InvalidJavadocPosition"/>-->
+ <!--<module name="JavadocMethod"/>-->
+ <module name="JavadocType"/>
+ <!--<module name="JavadocVariable"/>-->
+ <module name="JavadocStyle"/>
+ <!--<module name="MissingJavadocMethod"/>-->
+
+ <!-- Checks for Naming Conventions. -->
+ <!-- See https://checkstyle.org/config_naming.html -->
+ <module name="ConstantName"/>
+ <module name="LocalFinalVariableName"/>
+ <module name="LocalVariableName"/>
+ <module name="MemberName"/>
+ <module name="MethodName"/>
+ <module name="PackageName"/>
+ <module name="ParameterName"/>
+ <module name="StaticVariableName"/>
+ <module name="TypeName"/>
+
+ <!-- Checks for imports -->
+ <!-- See https://checkstyle.org/config_imports.html -->
+ <module name="AvoidStarImport">
+ <property name="allowClassImports" value="true"/>
+ <property name="allowStaticMemberImports" value="true"/>
+ </module>
+ <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
+ <module name="RedundantImport"/>
+ <module name="UnusedImports">
+ <property name="processJavadoc" value="false"/>
+ </module>
+
+ <!-- Checks for Size Violations. -->
+ <!-- See https://checkstyle.org/config_sizes.html -->
+ <module name="MethodLength">
+ <property name="max" value="300"/>
+ </module>
+ <module name="ParameterNumber">
+ <property name="max" value="20"/>
+ </module>
+
+ <!-- Checks for whitespace -->
+ <!-- See https://checkstyle.org/config_whitespace.html -->
+ <module name="EmptyForIteratorPad"/>
+ <module name="GenericWhitespace"/>
+ <module name="MethodParamPad"/>
+ <module name="NoWhitespaceAfter"/>
+ <module name="NoWhitespaceBefore"/>
+ <module name="OperatorWrap"/>
+ <module name="ParenPad"/>
+ <module name="TypecastParenPad"/>
+ <module name="WhitespaceAfter"/>
+ <module name="WhitespaceAround"/>
+
+ <!-- Modifier Checks -->
+ <!-- See https://checkstyle.org/config_modifiers.html -->
+ <module name="ModifierOrder"/>
+ <module name="RedundantModifier"/>
+
+ <!-- Checks for blocks. You know, those {}'s -->
+ <!-- See https://checkstyle.org/config_blocks.html -->
+ <module name="AvoidNestedBlocks"/>
+ <module name="EmptyBlock"/>
+ <module name="LeftCurly"/>
+ <module name="NeedBraces">
+ <property name="allowSingleLineStatement" value="true"/>
+ </module>
+ <module name="RightCurly"/>
+
+ <!-- Checks for common coding problems -->
+ <!-- See https://checkstyle.org/config_coding.html -->
+ <module name="EmptyStatement"/>
+ <module name="EqualsHashCode"/>
+ <module name="HiddenField">
+ <property name="ignoreConstructorParameter" value="true"/>
+ <property name="ignoreSetter" value="true"/>
+ </module>
+ <module name="IllegalInstantiation"/>
+ <module name="InnerAssignment"/>
+ <!--<module name="MagicNumber"/>-->
+ <module name="MissingSwitchDefault"/>
+ <module name="MultipleVariableDeclarations"/>
+ <module name="SimplifyBooleanExpression"/>
+ <module name="SimplifyBooleanReturn"/>
+
+ <!-- Checks for class design -->
+ <!-- See https://checkstyle.org/config_design.html -->
+ <!--<module name="DesignForExtension"/>-->
+ <!--<module name="FinalClass"/>-->
+ <module name="HideUtilityClassConstructor"/>
+ <module name="InterfaceIsType"/>
+ <module name="VisibilityModifier">
+ <property name="protectedAllowed" value="true"/>
+ <property name="allowPublicFinalFields" value="true"/>
+ </module>
+
+ <!-- Miscellaneous other checks. -->
+ <!-- See https://checkstyle.org/config_misc.html -->
+ <module name="ArrayTypeStyle"/>
+ <!--<module name="FinalParameters">-->
+ <module name="TodoComment"/>
+ <module name="UpperEll"/>
+
+ <!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
+ <module name="SuppressionXpathFilter">
+ <property name="file" value="${org.checkstyle.sun.suppressionxpathfilter.config}"
+ default="checkstyle-xpath-suppressions.xml" />
+ <property name="optional" value="true"/>
+ </module>
+
+ </module>
+
+</module>
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..28861d2
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..0517884
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,19 @@
+# Copyright 2020-present NAVER Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..d9508bb
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,186 @@
+#!/usr/bin/env sh
+
+# Copyright 2020-present NAVER Corp.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..d88ae3b
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,98 @@
+@rem Copyright 2020-present NAVER Corp.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..7ff0013
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,18 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rootProject.name = 'intellij-plugin'
+
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/DialogWrapperWithApply.java b/src/main/java/com/navercorp/openwhisk/intellij/common/DialogWrapperWithApply.java
new file mode 100644
index 0000000..7d56d5a
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/DialogWrapperWithApply.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+
+public abstract class DialogWrapperWithApply extends DialogWrapper {
+
+ protected ApplyAction myApplyAction;
+
+ protected DialogWrapperWithApply(@Nullable Project project, boolean canBeParent) {
+ super(project, canBeParent);
+ myApplyAction = new DialogWrapperWithApply.ApplyAction("Apply");
+ }
+
+ /**
+ * This method is invoked by default implementation of "Apply" action.
+ * This is convenient place to override functionality of "Apply" action.
+ */
+ protected void doApplyAction() {
+ // do noting
+ }
+
+ @NotNull
+ @Override
+ protected Action[] createActions() {
+ return new Action[]{
+ myCancelAction, myOKAction, myApplyAction
+ };
+ }
+
+ protected class ApplyAction extends DialogWrapperAction {
+
+ private boolean isApplied;
+
+ protected ApplyAction(@NotNull String name) {
+ super(name);
+ isApplied = false;
+ }
+
+ @Override
+ protected void doAction(ActionEvent e) {
+ doApplyAction();
+ isApplied = true;
+ }
+
+ public boolean isApplied() {
+ return isApplied;
+ }
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/Icons.java b/src/main/java/com/navercorp/openwhisk/intellij/common/Icons.java
new file mode 100644
index 0000000..eaa869e
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/Icons.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.util.IconLoader;
+import gnu.trove.THashMap;
+
+import javax.swing.*;
+import java.util.Map;
+
+public class Icons {
+
+ protected Icons() {
+ throw new UnsupportedOperationException("Utility classes should not have a public or default constructor.");
+ }
+
+ private static final Map<String, Icon> REGISTERED_ICONS = new THashMap<>();
+
+ public static final Icon ENTITY_TRIGGER = load("/icons/event.svg");
+ public static final Icon ENTITY_TRIGGER_ROOT = load("/icons/eventGroup.svg");
+
+ public static final Icon ARROW_UP = load("/icons/arrowUp.svg");
+ public static final Icon ARROW_DOWN = load("/icons/arrowDown.svg");
+
+ public static final Icon OPEN_DISK_HOVER = load("/icons/openDiskHover.svg");
+ public static final Icon RUN_ANYTHING = load("/icons/run_anything.svg");
+ public static final Icon YAML = load("/icons/yaml.svg");
+
+ public static final Icon KIND_JAVA = load("/icons/language/java/java.svg");
+ public static final Icon KIND_JS = load("/icons/language/javascript/javascript.svg");
+ public static final Icon KIND_GO = load("/icons/language/go/go.svg");
+ public static final Icon KIND_PYTHON = load("/icons/language/python/py.svg");
+ public static final Icon KIND_PHP = load("/icons/language/php/php.svg");
+ public static final Icon KIND_RUBY = load("/icons/language/ruby/rb.svg");
+ public static final Icon KIND_SWIFT = load("/icons/language/swift/sw.svg");
+ public static final Icon KIND_SEQUENCE = load("/icons/seq.svg");
+ public static final Icon KIND_DOCKER = load("/icons/language/docker/DockerCompose.svg");
+
+ private static Icon load(String path) {
+ try {
+ return IconLoader.getIcon(path);
+ } catch (Throwable t) {
+ return AllIcons.General.Warning;
+ }
+ }
+
+ private static Icon load(String key, String path) {
+ Icon icon = load(path);
+ REGISTERED_ICONS.put(key, icon);
+ return icon;
+ }
+
+ public static Icon getIcon(String key) {
+ return REGISTERED_ICONS.get(key);
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/error/NotExistFileException.java b/src/main/java/com/navercorp/openwhisk/intellij/common/error/NotExistFileException.java
new file mode 100644
index 0000000..04c94f4
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/error/NotExistFileException.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.error;
+
+public class NotExistFileException extends RuntimeException {
+
+ public NotExistFileException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/notification/SimpleNotifier.java b/src/main/java/com/navercorp/openwhisk/intellij/common/notification/SimpleNotifier.java
new file mode 100644
index 0000000..a0cc5e4
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/notification/SimpleNotifier.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.notification;
+
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationDisplayType;
+import com.intellij.notification.NotificationGroup;
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+
+public class SimpleNotifier {
+
+ private SimpleNotifier() {
+ }
+
+ private static class LazyHolder {
+ private static final SimpleNotifier INSTANCE = new SimpleNotifier();
+ }
+
+ public static SimpleNotifier getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ private static final NotificationGroup NOTIFICATION_GROUP =
+ new NotificationGroup("Simple Notification Group", NotificationDisplayType.STICKY_BALLOON, true);
+
+ public Notification notify(@NotNull String content, @NotNull final NotificationType type) {
+ return notify(null, content, type);
+ }
+
+ public Notification notify(Project project, @NotNull String content, @NotNull final NotificationType type) {
+ final Notification notification = NOTIFICATION_GROUP.createNotification(content, type);
+ notification.notify(project);
+ return notification;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/service/WhiskService.java b/src/main/java/com/navercorp/openwhisk/intellij/common/service/WhiskService.java
new file mode 100644
index 0000000..cd58f06
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/service/WhiskService.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.service;
+
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+@State(
+ name = "whisk",
+ storages = {
+ @Storage("whisk.xml")
+ }
+)
+public class WhiskService implements PersistentStateComponent<WhiskService> {
+ private static final Logger LOG = Logger.getInstance(WhiskService.class);
+
+ private String endpoints;
+
+ @Nullable
+ @Override
+ public WhiskService getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(@NotNull WhiskService state) {
+ LOG.info("Save state");
+ XmlSerializerUtil.copyBean(state, this);
+ }
+
+ public String getEndpoints() {
+ return endpoints;
+ }
+
+ public void setEndpoints(String endpoints) {
+ this.endpoints = endpoints;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/service/WskDeployService.java b/src/main/java/com/navercorp/openwhisk/intellij/common/service/WskDeployService.java
new file mode 100644
index 0000000..9627678
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/service/WskDeployService.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.service;
+
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+@State(
+ name = "wskdeploy",
+ storages = {
+ @Storage("wskdeploy.xml")
+ }
+)
+public class WskDeployService implements PersistentStateComponent<WskDeployService> {
+ private static final Logger LOG = Logger.getInstance(WskDeployService.class);
+
+ private String wskdeployPath;
+ private String wskdeployName;
+
+ @Nullable
+ @Override
+ public WskDeployService getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(@NotNull WskDeployService state) {
+ LOG.info("Save wskdeploy");
+ XmlSerializerUtil.copyBean(state, this);
+ }
+
+ public String getWskdeployPath() {
+ return wskdeployPath;
+ }
+
+ public void setWskdeployPath(String wskdeployPath) {
+ this.wskdeployPath = wskdeployPath;
+ }
+
+ public String getWskdeployName() {
+ return wskdeployName;
+ }
+
+ public void setWskdeployName(String wskdeployName) {
+ this.wskdeployName = wskdeployName;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/utils/CommandUtils.java b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/CommandUtils.java
new file mode 100644
index 0000000..4f35ec5
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/CommandUtils.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.utils;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy.WskDeployCmdResponse;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+public class CommandUtils {
+
+ private static final Logger LOG = Logger.getInstance(CommandUtils.class);
+
+ protected CommandUtils() {
+ throw new UnsupportedOperationException("Utility classes should not have a public or default constructor.");
+ }
+
+ public static WskDeployCmdResponse runCommand(String[] command)
+ throws IOException, InterruptedException {
+ ProcessBuilder builder = new ProcessBuilder(command);
+ Process process = builder.start();
+
+ // read std output
+ BufferedReader reader =
+ new BufferedReader(new InputStreamReader(process.getInputStream()));
+ StringBuilder output = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ output.append(line + "\n");
+ }
+
+ // read error output
+ BufferedReader errReader =
+ new BufferedReader(new InputStreamReader(process.getErrorStream()));
+ StringBuilder errOutput = new StringBuilder();
+ String errLine;
+ while ((errLine = errReader.readLine()) != null) {
+ errOutput.append(errLine + "\n");
+ }
+
+ int exitCode = process.waitFor();
+ return new WskDeployCmdResponse(exitCode, output.toString(), errOutput.toString());
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/utils/EventUtils.java b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/EventUtils.java
new file mode 100644
index 0000000..df936da
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/EventUtils.java
@@ -0,0 +1,57 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.utils;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.messages.MessageBus;
+import com.intellij.util.messages.MessageBusConnection;
+import com.intellij.util.messages.Topic;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class EventUtils {
+
+ protected EventUtils() {
+ throw new UnsupportedOperationException("Utility classes should not have a public or default constructor.");
+ }
+
+ @NotNull
+ private static MessageBusConnection connect(@NotNull Project project, @Nullable Disposable parentDisposable) {
+ MessageBus messageBus = project.getMessageBus();
+ return parentDisposable == null ? messageBus.connect(project) : messageBus.connect(parentDisposable);
+ }
+
+ public static <T> void subscribe(Project project, @Nullable Disposable parentDisposable, Topic<T> topic, T handler) {
+ MessageBusConnection messageBusConnection = connect(project, parentDisposable);
+ messageBusConnection.subscribe(topic, handler);
+
+ }
+
+ public static <T> void publish(@Nullable Project project, Topic<T> topic, ParametricRunnable.Basic<T> callback) {
+ if (project != null) {
+ try {
+ MessageBus messageBus = project.getMessageBus();
+ T publisher = messageBus.syncPublisher(topic);
+ callback.run(publisher);
+ } catch (ProcessCanceledException ignore) {
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/utils/FileUtils.java b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/FileUtils.java
new file mode 100644
index 0000000..e396c7d
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/FileUtils.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.utils;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.ExecutableWhiskAction;
+import com.navercorp.openwhisk.intellij.common.whisk.model.activation.WhiskActivationWithLogs;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Optional;
+
+import static com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils.writeWhiskActivationToJson;
+
+public class FileUtils {
+
+ private static final Logger LOG = Logger.getInstance(FileUtils.class);
+
+ protected FileUtils() {
+ throw new UnsupportedOperationException("Utility classes should not have a public or default constructor.");
+ }
+
+ /**
+ * It accumulates in the .gradle/caches subfolder and files are not automatically cleared unless you delete the cache directory.
+ * TODO Delete the cache file globally.
+ * TODO Use LightVirtualFile instead of local file.
+ */
+ public static VirtualFile writeActionToFile(String basePath, ExecutableWhiskAction action) throws IOException {
+ File dir = new File(basePath);
+ if (!dir.exists()) {
+ dir.mkdir();
+ }
+
+ final String path = basePath + "/" + action.getName() + action.getKindExtension();
+ File f = new File(path);
+ LOG.info("Open action file: " + f.getAbsolutePath());
+
+ FileWriter fw = new FileWriter(f);
+
+ if (action.getExec().isBinary()) {
+ fw.write("This action was created as a zip file, and you can't see the code here.");
+ } else {
+ String code = Optional.ofNullable(action.getExec().getCode()).orElse("This action is empty");
+ fw.write(code);
+ }
+ fw.close();
+
+ return VfsUtil.findFileByIoFile(f, true);
+ }
+
+ /**
+ * It accumulates in the .gradle/caches subfolder and files are not automatically cleared unless you delete the cache directory.
+ * TODO Delete the cache file globally.
+ * TODO Use LightVirtualFile instead of local file.
+ */
+ public static VirtualFile writeActivationToFile(String basePath, WhiskActivationWithLogs activation) throws IOException {
+ File dir = new File(basePath);
+ if (!dir.exists()) {
+ dir.mkdir();
+ }
+
+ File f = new File(basePath + "/" + activation.getName() + "-" + activation.getActivationId() + ".json");
+ LOG.info("Open activation file: " + f.getAbsolutePath());
+
+ FileWriter fw = new FileWriter(f);
+ fw.write(writeWhiskActivationToJson(activation));
+ fw.close();
+
+ return VfsUtil.findFileByIoFile(f, true);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/utils/JsonParserUtils.java b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/JsonParserUtils.java
new file mode 100644
index 0000000..656482c
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/JsonParserUtils.java
@@ -0,0 +1,214 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import org.apache.commons.lang.StringUtils;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.ExecutableWhiskAction;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.WhiskActionMetaData;
+import com.navercorp.openwhisk.intellij.common.whisk.model.activation.WhiskActivationMetaData;
+import com.navercorp.openwhisk.intellij.common.whisk.model.activation.WhiskActivationWithLogs;
+import com.navercorp.openwhisk.intellij.common.whisk.model.exec.CodeExec;
+import com.navercorp.openwhisk.intellij.common.whisk.model.exec.CodeExecSerializer;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackage;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackageWithActions;
+import com.navercorp.openwhisk.intellij.common.whisk.model.trigger.ExecutableWhiskTrigger;
+import com.navercorp.openwhisk.intellij.common.whisk.model.trigger.WhiskRule;
+import com.navercorp.openwhisk.intellij.common.whisk.model.trigger.WhiskTriggerMetaData;
+
+import java.io.IOException;
+import java.util.*;
+
+public class JsonParserUtils {
+ private static ObjectMapper mapper = new ObjectMapper();
+ private static SimpleModule simpleModule = new SimpleModule();
+
+ protected JsonParserUtils() {
+ throw new UnsupportedOperationException("Utility classes should not have a public or default constructor.");
+ }
+
+ static {
+ simpleModule.addSerializer(CodeExec.class, new CodeExecSerializer());
+ mapper.registerModule(simpleModule);
+ }
+
+ public static List<WhiskActionMetaData> parseWhiskActions(String actions) throws IOException {
+ if (StringUtils.isNotEmpty(actions)) {
+ return Arrays.asList(mapper.readValue(actions, WhiskActionMetaData[].class));
+ } else {
+ return new ArrayList<>();
+ }
+ }
+
+ public static Optional<ExecutableWhiskAction> parseWhiskAction(String action) throws IOException {
+ if (StringUtils.isNotEmpty(action)) {
+ return Optional.of(mapper.readValue(action, ExecutableWhiskAction.class));
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ public static List<WhiskPackage> parseWhiskPackages(String packages) throws IOException {
+ if (StringUtils.isNotEmpty(packages)) {
+ return Arrays.asList(mapper.readValue(packages, WhiskPackage[].class));
+ } else {
+ return new ArrayList<>();
+ }
+ }
+
+ public static Optional<WhiskPackageWithActions> parseWhiskPackage(String pkg) throws IOException {
+ if (StringUtils.isNotEmpty(pkg)) {
+ return Optional.of(mapper.readValue(pkg, WhiskPackageWithActions.class));
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ // TODO test
+ public static List<WhiskEndpoint> parseWhiskEndpoints(String endpoints) throws IOException {
+ if (StringUtils.isNotEmpty(endpoints)) {
+ return Arrays.asList(mapper.readValue(endpoints, WhiskEndpoint[].class));
+ } else {
+ return new ArrayList<>();
+ }
+ }
+
+ // TODO test
+ public static String writeEndpointsToJson(List<WhiskEndpoint> ep) throws JsonProcessingException {
+ return mapper.writeValueAsString(ep);
+ }
+
+ // TODO test
+ public static String[] parseWhiskNamespace(String namespaces) throws IOException {
+ if (StringUtils.isNotEmpty(namespaces)) {
+ return mapper.readValue(namespaces, String[].class);
+ } else {
+ return new String[]{};
+ }
+ }
+
+ // TODO test
+ public static List<WhiskActivationMetaData> parseWhiskActivations(String actions) throws IOException {
+ if (StringUtils.isNotEmpty(actions)) {
+ return Arrays.asList(mapper.readValue(actions, WhiskActivationMetaData[].class));
+ } else {
+ return new ArrayList<>();
+ }
+ }
+
+ // TODO test
+ public static Optional<WhiskActivationWithLogs> parseWhiskActivation(String actions) throws IOException {
+ if (StringUtils.isNotEmpty(actions)) {
+ return Optional.of(mapper.readValue(actions, WhiskActivationWithLogs.class));
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ // TODO test
+ public static String writeWhiskActivationToJson(WhiskActivationWithLogs activation) throws JsonProcessingException {
+ return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(activation);
+ }
+
+ public static List<WhiskTriggerMetaData> parseWhiskTriggers(String triggers) throws IOException {
+ if (StringUtils.isNotEmpty(triggers)) {
+ return Arrays.asList(mapper.readValue(triggers, WhiskTriggerMetaData[].class));
+ } else {
+ return new ArrayList<>();
+ }
+ }
+
+ public static Optional<ExecutableWhiskTrigger> parseWhiskTrigger(String triggers) throws IOException {
+ if (StringUtils.isNotEmpty(triggers)) {
+ return Optional.of(mapper.readValue(triggers, ExecutableWhiskTrigger.class));
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ // TODO test
+ public static Optional<WhiskRule> parseWhiskRule(String rule) throws IOException {
+ if (StringUtils.isNotEmpty(rule)) {
+ return Optional.of(mapper.readValue(rule, WhiskRule.class));
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ // TODO test
+ public static String writeParameterToJson(List<Map<String, Object>> params) throws JsonProcessingException {
+ return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(ParameterUtils.listMapToMap(params));
+ }
+
+ // TODO test
+ public static List<Map<String, Object>> parseListMap(String json) throws IOException {
+ if (StringUtils.isNotEmpty(json)) {
+ return mapper.readValue(json, new TypeReference<List<Map<String, Object>>>() {
+ });
+ } else {
+ return new ArrayList<>();
+ }
+ }
+
+ // TODO test
+ public static String writeListMapToJson(List<Map<String, Object>> maps) throws JsonProcessingException {
+ return mapper.writer().writeValueAsString(maps);
+ }
+
+ // TODO test
+ public static Map<String, Object> parseMap(String json) {
+ if (StringUtils.isNotEmpty(json)) {
+ try {
+ return mapper.readValue(json, Map.class);
+ } catch (IOException e) {
+ return new LinkedHashMap<>();
+ }
+ } else {
+ return new LinkedHashMap<>();
+ }
+ }
+
+ // TODO test
+ public static String writeMapToJson(Map<String, Object> map) throws JsonProcessingException {
+ return mapper.writeValueAsString(map);
+ }
+
+ // TODO test
+ public static boolean isValidJson(final String json) throws IOException {
+ boolean valid = true;
+ try {
+ mapper.readTree(json);
+ } catch (JsonProcessingException e) {
+ valid = false;
+ }
+ return valid;
+ }
+
+ // TODO test
+ public static String beautifyJson(String json) throws IOException {
+ if (StringUtils.isNotEmpty(json)) {
+ Map<String, Object> j = mapper.readValue(json, Map.class);
+ return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(j);
+ } else {
+ return "";
+ }
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ParameterUtils.java b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ParameterUtils.java
new file mode 100644
index 0000000..c6de207
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ParameterUtils.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.utils;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.io.IOException;
+import java.util.*;
+
+public class ParameterUtils {
+
+ protected ParameterUtils() {
+ throw new UnsupportedOperationException("Utility classes should not have a public or default constructor.");
+ }
+
+ // TODO test
+ public static Map<String, Object> listMapToMap(List<Map<String, Object>> params) {
+ Map<String, Object> map = new LinkedHashMap<>();
+ for (Map<String, Object> p : params) {
+ map.put((String) p.get("key"), p.get("value"));
+ }
+ return map;
+ }
+
+ public static List<Map<String, Object>> mapToListMap(Map<String, Object> params) {
+ List<Map<String, Object>> list = new ArrayList<>();
+ for (String key : params.keySet()) {
+ Object v = params.get(key);
+ Map<String, Object> m = new LinkedHashMap<>();
+ m.put("key", key);
+ m.put("value", v);
+ list.add(m);
+ }
+ return list;
+ }
+
+ public static Optional<String> validateParams(String params) {
+ if (StringUtils.isEmpty(params)) {
+ return Optional.of("{}");
+ } else {
+ try {
+ if (JsonParserUtils.isValidJson(params)) {
+ return Optional.of(params);
+ } else {
+ return Optional.empty();
+ }
+ } catch (IOException e) {
+ return Optional.empty();
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ParametricRunnable.java b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ParametricRunnable.java
new file mode 100644
index 0000000..5964db8
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ParametricRunnable.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.utils;
+
+@FunctionalInterface
+public interface ParametricRunnable<P, E extends Throwable> {
+ void run(P parameter) throws E;
+
+ interface Basic<P> extends ParametricRunnable<P, RuntimeException> {
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ValidationUtils.java b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ValidationUtils.java
new file mode 100644
index 0000000..e243226
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/ValidationUtils.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.utils;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy.WskDeployCmdResponse;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import static com.navercorp.openwhisk.intellij.common.utils.CommandUtils.runCommand;
+
+public class ValidationUtils {
+ private static final Logger LOG = Logger.getInstance(ValidationUtils.class);
+
+ protected ValidationUtils() {
+ throw new UnsupportedOperationException("Utility classes should not have a public or default constructor.");
+ }
+
+ public static Optional<VirtualFile> validateWskDeploy(Optional<VirtualFile> wskdeploy) {
+ return wskdeploy.flatMap(wskdeployFile -> {
+ String[] cmd = new String[]{wskdeployFile.getPath(), "version"};
+ try {
+ WskDeployCmdResponse response = runCommand(cmd);
+ if (response.getExistCode() == 0) {
+ return Optional.of(wskdeployFile);
+ } else {
+ LOG.error(response.getErrorOutput());
+ return Optional.empty();
+ }
+ } catch (IOException | InterruptedException e) {
+ LOG.error(e);
+ return Optional.empty();
+ }
+ });
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/utils/WhiskUtils.java b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/WhiskUtils.java
new file mode 100644
index 0000000..d35c368
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/utils/WhiskUtils.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.utils;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskNamespace;
+
+import java.util.List;
+import java.util.Optional;
+
+public class WhiskUtils {
+ private static final Logger LOG = Logger.getInstance(WhiskUtils.class);
+
+ protected WhiskUtils() {
+ throw new UnsupportedOperationException("Utility classes should not have a public or default constructor.");
+ }
+
+ public static Optional<WhiskAuth> findWhiskAuth(List<WhiskEndpoint> endpoints, WhiskNamespace namespace) {
+ for (WhiskEndpoint ep : endpoints) {
+ for (WhiskNamespace np : ep.getNamespaces()) {
+ if (np.getAuth().equals(namespace.getAuth()) && np.getPath().equals(namespace.getPath())) {
+ return Optional.of(new WhiskAuth(np.getAuth(), ep.getApihost()));
+ }
+ }
+ }
+ return Optional.empty();
+ }
+
+ public static Optional<WhiskNamespace> findWhiskNamespace(List<WhiskEndpoint> endpoints, String auth) {
+ for (WhiskEndpoint ep : endpoints) {
+ for (WhiskNamespace np : ep.getNamespaces()) {
+ if (np.getAuth().equals(auth)) {
+ return Optional.of(np);
+ }
+ }
+ }
+ return Optional.empty();
+ }
+
+ public static String getApihHostWithProtocol(String apiHost) {
+ if (!apiHost.toLowerCase().matches("^\\w+://.*")) {
+ apiHost = "https://" + apiHost;
+ }
+ return apiHost;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Binding.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Binding.java
new file mode 100644
index 0000000..3baef86
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Binding.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model;
+
+import java.util.Objects;
+
+public class Binding {
+
+ private String namespace;
+ private String name;
+
+ public Binding(String namespace, String name) {
+ this.namespace = namespace;
+ this.name = name;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Binding binding = (Binding) o;
+ return Objects.equals(namespace, binding.namespace)
+ && Objects.equals(name, binding.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(namespace, name);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Limits.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Limits.java
new file mode 100644
index 0000000..7f82578
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Limits.java
@@ -0,0 +1,88 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model;
+
+public class Limits {
+ private int concurrency;
+ private int logs;
+ private int memory;
+ private int timeout;
+
+ public Limits() {
+ }
+
+ public Limits(int concurrency, int logs, int memory, int timeout) {
+ this.concurrency = concurrency;
+ this.logs = logs;
+ this.memory = memory;
+ this.timeout = timeout;
+ }
+
+ public int getConcurrency() {
+ return concurrency;
+ }
+
+ public void setConcurrency(int concurrency) {
+ this.concurrency = concurrency;
+ }
+
+ public int getLogs() {
+ return logs;
+ }
+
+ public void setLogs(int logs) {
+ this.logs = logs;
+ }
+
+ public int getMemory() {
+ return memory;
+ }
+
+ public void setMemory(int memory) {
+ this.memory = memory;
+ }
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ public void setTimeout(int timeout) {
+ this.timeout = timeout;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Limits limits = (Limits) o;
+
+ if (concurrency != limits.concurrency) return false;
+ if (logs != limits.logs) return false;
+ if (memory != limits.memory) return false;
+ return timeout == limits.timeout;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = concurrency;
+ result = 31 * result + logs;
+ result = 31 * result + memory;
+ result = 31 * result + timeout;
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Runtime.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Runtime.java
new file mode 100644
index 0000000..8de09df
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/Runtime.java
@@ -0,0 +1,188 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model;
+
+/**
+ * Set the type of runtime based on upstream
+ * - https://github.com/apache/openwhisk/blob/master/ansible/files/runtimes.json
+ *
+ * The runtime used for each endpoint may be different, so use it according to the policy of the endpoint users are using.
+ */
+public enum Runtime {
+ NODE_6("nodejs", ".js", "6", false, true),
+ NODE_8("nodejs", ".js", "8", false, true),
+ NODE_10("nodejs", ".js", "10", true, false),
+ NODE_12("nodejs", ".js", "12", false, false),
+ NODE_14("nodejs", ".js", "14", false, false),
+ PYTHON_2("python", ".py", "2", false, false),
+ PYTHON_3("python", ".py", "3", true, false),
+ JAVA("java", ".java", "8", true, false),
+ SWIFT_3_1_1("swift", ".swift", "3.1.1", false, true),
+ SWIFT_4_2("swift", ".swift", "4.2", true, false),
+ SWIFT_5_1("swift", ".swift", "5.1", false, false),
+ PHP_7_3("php", ".php", "7.3", false, false),
+ PHP_7_4("php", ".php", "7.4", true, false),
+ GO_1_11("go", ".go", "1.11", true, false),
+ RUBY_2_5("ruby", ".rb", "2.5", true, false),
+ SEQUENCE("sequence", "", "", true, false),
+ DOCKER("blackbox", "", "", true, false);
+
+ private String name;
+ private String extension;
+ private String version;
+ private boolean defaultRuntime;
+ private boolean deprecated;
+
+ Runtime(String name, String extension, String version, boolean defaultRuntime, boolean deprecated) {
+ this.name = name;
+ this.extension = extension;
+ this.version = version;
+ this.defaultRuntime = defaultRuntime;
+ this.deprecated = deprecated;
+ }
+
+ @Override
+ public String toString() {
+ switch (name) {
+ case "java":
+ return name;
+ default:
+ String runtime = name;
+ if (version.length() > 0) {
+ runtime += ":" + version;
+ }
+
+ if (deprecated) {
+ runtime += " (Deprecated)";
+ }
+ return runtime;
+ }
+ }
+
+ public static Runtime toRuntime(String kind) {
+ switch (kind) {
+ case "nodejs:6":
+ return NODE_6;
+ case "nodejs:8":
+ return NODE_8;
+ case "nodejs:10":
+ return NODE_10;
+ case "nodejs:12":
+ return NODE_12;
+ case "nodejs:14":
+ return NODE_14;
+ case "python:2":
+ return PYTHON_2;
+ case "python:3":
+ return PYTHON_3;
+ case "java":
+ return JAVA;
+ case "swift:3.1.1":
+ return SWIFT_3_1_1;
+ case "swift:4.2":
+ return SWIFT_4_2;
+ case "swift:5.1":
+ return SWIFT_5_1;
+ case "php:7.3":
+ return PHP_7_3;
+ case "php:7.4":
+ return PHP_7_4;
+ case "go:1.11":
+ return GO_1_11;
+ case "ruby:2.5":
+ return RUBY_2_5;
+ case "sequence":
+ return SEQUENCE;
+ default:
+ return DOCKER;
+ }
+ }
+
+ public static Runtime toRuntime(int index) {
+ switch (index) {
+ case 0:
+ return NODE_6;
+ case 1:
+ return NODE_8;
+ case 2:
+ return NODE_10;
+ case 3:
+ return NODE_12;
+ case 4:
+ return NODE_14;
+ case 5:
+ return PYTHON_2;
+ case 6:
+ return PYTHON_3;
+ case 7:
+ return JAVA;
+ case 8:
+ return SWIFT_3_1_1;
+ case 9:
+ return SWIFT_4_2;
+ case 10:
+ return SWIFT_5_1;
+ case 11:
+ return PHP_7_3;
+ case 12:
+ return PHP_7_4;
+ case 13:
+ return GO_1_11;
+ case 14:
+ return RUBY_2_5;
+ case 15:
+ return SEQUENCE;
+ default:
+ return DOCKER;
+ }
+ }
+
+ public static Runtime toCodeType(int index) {
+ switch (index) {
+ case 0:
+ return NODE_6;
+ case 1:
+ return NODE_8;
+ case 2:
+ return NODE_10;
+ case 3:
+ return NODE_12;
+ case 4:
+ return NODE_14;
+ case 5:
+ return PYTHON_2;
+ case 6:
+ return PYTHON_3;
+ case 7:
+ return JAVA;
+ case 8:
+ return SWIFT_3_1_1;
+ case 9:
+ return SWIFT_4_2;
+ case 10:
+ return SWIFT_5_1;
+ case 11:
+ return PHP_7_3;
+ case 12:
+ return PHP_7_4;
+ case 13:
+ return GO_1_11;
+ default:
+ return RUBY_2_5;
+ }
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskAuth.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskAuth.java
new file mode 100644
index 0000000..a044de8
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskAuth.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model;
+
+import com.navercorp.openwhisk.intellij.common.utils.WhiskUtils;
+
+import java.util.Base64;
+
+public class WhiskAuth {
+ private String auth;
+ private String apihost;
+
+ public WhiskAuth() {
+ }
+
+ public WhiskAuth(String auth, String apihost) {
+ this.auth = auth;
+ this.apihost = WhiskUtils.getApihHostWithProtocol(apihost);
+ }
+
+ public String getAuth() {
+ return auth;
+ }
+
+ public void setAuth(String auth) {
+ this.auth = auth;
+ }
+
+ public String getApihost() {
+ return apihost;
+ }
+
+ public void setApihost(String apihost) {
+ this.apihost = WhiskUtils.getApihHostWithProtocol(apihost);
+ }
+
+ public String getBasicAuthHeader() {
+ return "Basic " + Base64.getEncoder().encodeToString(auth.getBytes());
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskAuthWithName.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskAuthWithName.java
new file mode 100644
index 0000000..72b176e
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskAuthWithName.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model;
+
+public class WhiskAuthWithName {
+ private WhiskAuth auth;
+ private String name;
+
+ public WhiskAuthWithName(WhiskAuth auth, String name) {
+ this.auth = auth;
+ this.name = name;
+ }
+
+ public WhiskAuth getAuth() {
+ return auth;
+ }
+
+ public void setAuth(WhiskAuth auth) {
+ this.auth = auth;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name + " (" + auth.getApihost() + ")";
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskEndpoint.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskEndpoint.java
new file mode 100644
index 0000000..d36fb12
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskEndpoint.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model;
+
+import com.navercorp.openwhisk.intellij.common.utils.WhiskUtils;
+
+import java.util.List;
+
+public class WhiskEndpoint {
+ private String alias;
+ private String apihost;
+ private List<WhiskNamespace> namespaces;
+
+ public WhiskEndpoint() {
+ }
+
+ public WhiskEndpoint(String alias, String apihost, List<WhiskNamespace> namespaces) {
+ this.alias = alias;
+ this.apihost = WhiskUtils.getApihHostWithProtocol(apihost);
+ this.namespaces = namespaces;
+ }
+
+ public String getAlias() {
+ return alias;
+ }
+
+ public void setAlias(String alias) {
+ this.alias = alias;
+ }
+
+ public String getApihost() {
+ return apihost;
+ }
+
+ public void setApihost(String apihost) {
+ this.apihost = WhiskUtils.getApihHostWithProtocol(apihost);
+ }
+
+ public List<WhiskNamespace> getNamespaces() {
+ return namespaces;
+ }
+
+ public void setNamespaces(List<WhiskNamespace> namespaces) {
+ this.namespaces = namespaces;
+ }
+
+ public void addNamespaces(WhiskNamespace namespace) {
+ this.namespaces.add(namespace);
+ }
+
+ public String displayName() {
+ return this.alias + " (" + this.apihost + ")";
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskNamespace.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskNamespace.java
new file mode 100644
index 0000000..46c9376
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/WhiskNamespace.java
@@ -0,0 +1,113 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.WhiskActionMetaData;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackage;
+import com.navercorp.openwhisk.intellij.common.whisk.model.trigger.WhiskTriggerMetaData;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@JsonIgnoreProperties(value = {"packages", "actions"})
+public class WhiskNamespace {
+ private String auth;
+ private String path;
+ private List<WhiskPackage> packages = new ArrayList<>();
+ private List<WhiskActionMetaData> actions = new ArrayList<>();
+ private List<WhiskTriggerMetaData> triggers = new ArrayList<>();
+
+ public WhiskNamespace() {
+ }
+
+ public WhiskNamespace(String auth, String path) {
+ this.auth = auth;
+ this.path = path;
+ }
+
+ public WhiskNamespace(String auth, String path, List<WhiskPackage> packages, List<WhiskActionMetaData> actions, List<WhiskTriggerMetaData> triggers) {
+ this.auth = auth;
+ this.path = path;
+ this.packages = packages;
+ this.actions = actions;
+ this.triggers = triggers;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getAuth() {
+ return auth;
+ }
+
+ public void setAuth(String auth) {
+ this.auth = auth;
+ }
+
+ public List<WhiskPackage> getPackages() {
+ return packages;
+ }
+
+ public void setPackages(List<WhiskPackage> packages) {
+ this.packages = packages;
+ }
+
+ public List<WhiskActionMetaData> getActions() {
+ return actions;
+ }
+
+ public void setActions(List<WhiskActionMetaData> actions) {
+ this.actions = actions;
+ }
+
+ public List<WhiskTriggerMetaData> getTriggers() {
+ return triggers;
+ }
+
+ public void setTriggers(List<WhiskTriggerMetaData> triggers) {
+ this.triggers = triggers;
+ }
+
+ @Override
+ public String toString() {
+ return path;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ WhiskNamespace that = (WhiskNamespace) o;
+ return Objects.equals(auth, that.auth)
+ && Objects.equals(path, that.path)
+ && Objects.equals(packages, that.packages)
+ && Objects.equals(actions, that.actions)
+ && Objects.equals(triggers, that.triggers);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(auth, path, packages, actions, triggers);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/CompactWhiskAction.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/CompactWhiskAction.java
new file mode 100644
index 0000000..e0b2434
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/CompactWhiskAction.java
@@ -0,0 +1,136 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.action;
+
+import com.navercorp.openwhisk.intellij.common.Icons;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class CompactWhiskAction {
+ private String name;
+ private String version;
+ private List<Map<String, Object>> annotations = new ArrayList<>();
+
+ public CompactWhiskAction() {
+ }
+
+ public CompactWhiskAction(String name, String version, List<Map<String, Object>> annotations) {
+ this.name = name;
+ this.version = version;
+ this.annotations = annotations;
+ }
+
+ public String getKind() {
+ for (Map<String, Object> a : this.annotations) {
+ if ("exec".equals(a.get("key"))) {
+ return (String) a.get("value");
+ }
+ }
+ return "";
+ }
+
+ public String getKindExtension() {
+ String kind = getKind();
+ if (kind.contains("java")) {
+ return ".java";
+ } else if (kind.contains("nodejs")) {
+ return ".js";
+ } else if (kind.contains("python")) {
+ return ".py";
+ } else if (kind.contains("swift")) {
+ return ".swift";
+ } else if (kind.contains("php")) {
+ return ".php";
+ } else if (kind.contains("go")) {
+ return ".go";
+ } else if (kind.contains("ruby")) {
+ return ".rb";
+ } else {
+ return "";
+ }
+ }
+
+ public Icon getKindIcon() {
+ String kind = getKind();
+ if (kind.contains("java")) {
+ return Icons.KIND_JAVA;
+ } else if (kind.contains("nodejs")) {
+ return Icons.KIND_JS;
+ } else if (kind.contains("python")) {
+ return Icons.KIND_PYTHON;
+ } else if (kind.contains("swift")) {
+ return Icons.KIND_SWIFT;
+ } else if (kind.contains("php")) {
+ return Icons.KIND_PHP;
+ } else if (kind.contains("go")) {
+ return Icons.KIND_GO;
+ } else if (kind.contains("ruby")) {
+ return Icons.KIND_RUBY;
+ } else if (kind.contains("sequence")) {
+ return Icons.KIND_SEQUENCE;
+ } else {
+ return Icons.KIND_DOCKER;
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public List<Map<String, Object>> getAnnotations() {
+ return annotations;
+ }
+
+ public void setAnnotations(List<Map<String, Object>> annotations) {
+ this.annotations = annotations;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ CompactWhiskAction that = (CompactWhiskAction) o;
+
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ if (version != null ? !version.equals(that.version) : that.version != null) return false;
+ return annotations != null ? annotations.equals(that.annotations) : that.annotations == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (version != null ? version.hashCode() : 0);
+ result = 31 * result + (annotations != null ? annotations.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/ExecutableWhiskAction.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/ExecutableWhiskAction.java
new file mode 100644
index 0000000..6c6a41e
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/ExecutableWhiskAction.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.action;
+
+import com.navercorp.openwhisk.intellij.common.whisk.model.Limits;
+import com.navercorp.openwhisk.intellij.common.whisk.model.exec.CodeExec;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+public class ExecutableWhiskAction extends WhiskAction<CodeExec> {
+ private List<Map<String, Object>> parameters = new ArrayList<>();
+
+ public ExecutableWhiskAction() {
+ }
+
+ public ExecutableWhiskAction(List<Map<String, Object>> parameters) {
+ this.parameters = parameters;
+ }
+
+ public ExecutableWhiskAction(String name, String namespace, String version, long updated, boolean publish,
+ List<Map<String, Object>> annotations,
+ Limits limits,
+ CodeExec exec,
+ List<Map<String, Object>> parameters) {
+ super(name, namespace, version, updated, publish, annotations, limits, exec);
+ this.parameters = parameters;
+ }
+
+ public List<Map<String, Object>> getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(List<Map<String, Object>> parameters) {
+ this.parameters = parameters;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+ ExecutableWhiskAction that = (ExecutableWhiskAction) o;
+ return Objects.equals(parameters, that.parameters);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), parameters);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/WhiskAction.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/WhiskAction.java
new file mode 100644
index 0000000..feff4e2
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/WhiskAction.java
@@ -0,0 +1,292 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.action;
+
+import com.navercorp.openwhisk.intellij.common.Icons;
+import com.navercorp.openwhisk.intellij.common.whisk.model.Limits;
+import com.navercorp.openwhisk.intellij.common.whisk.model.exec.Exec;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public abstract class WhiskAction<E extends Exec> {
+ private String name;
+ private String namespace;
+ private String version;
+ private long updated;
+ private boolean publish;
+ private List<Map<String, Object>> annotations = new ArrayList<>();
+ private Limits limits;
+ private E exec;
+
+ public WhiskAction() {
+ }
+
+ public WhiskAction(String name, String namespace, String version, long updated, boolean publish,
+ List<Map<String, Object>> annotations,
+ Limits limits,
+ E exec) {
+ this.name = name;
+ this.namespace = namespace;
+ this.version = version;
+ this.updated = updated;
+ this.publish = publish;
+ this.annotations = annotations;
+ this.limits = limits;
+ this.exec = exec;
+ }
+
+ public Optional<String> getWhiskPackage() {
+ if (namespace == null) {
+ return Optional.empty();
+ } else {
+ String[] ns = namespace.split("/");
+ if (ns.length == 1) {
+ return Optional.empty();
+ } else {
+ return Optional.of(ns[1]);
+ }
+ }
+ }
+
+ public String getNamespacePath() {
+ return namespace.split("/")[0];
+ }
+
+ public String getFullyQualifiedName() {
+ return namespace + "/" + name;
+ }
+
+ public String getKind() {
+ for (Map<String, Object> a : this.annotations) {
+ if ("exec".equals(a.get("key"))) {
+ return (String) a.get("value");
+ }
+ }
+ return "";
+ }
+
+ public Optional<String> getCodeType() {
+ for (Map<String, Object> a : this.annotations) {
+ if ("code-type".equals(a.get("key"))) {
+ return Optional.ofNullable((String) a.get("value"));
+ }
+ }
+ return Optional.empty();
+ }
+
+ public String getKindExtension() {
+ String kind = getKind();
+ if (kind.contains("java")) {
+ return ".java";
+ } else if (kind.contains("nodejs")) {
+ return ".js";
+ } else if (kind.contains("python")) {
+ return ".py";
+ } else if (kind.contains("swift")) {
+ return ".swift";
+ } else if (kind.contains("php")) {
+ return ".php";
+ } else if (kind.contains("go")) {
+ return ".go";
+ } else if (kind.contains("ruby")) {
+ return ".rb";
+ } else if (kind.contains("blackbox")) {
+ return getCodeType().map(codeType -> {
+ if (codeType.contains("java")) {
+ return ".java";
+ } else if (codeType.contains("nodejs")) {
+ return ".js";
+ } else if (codeType.contains("python")) {
+ return ".py";
+ } else if (codeType.contains("swift")) {
+ return ".swift";
+ } else if (codeType.contains("php")) {
+ return ".php";
+ } else if (codeType.contains("go")) {
+ return ".go";
+ } else if (codeType.contains("ruby")) {
+ return ".rb";
+ }
+ return "";
+ }).orElse("");
+ }
+ return "";
+ }
+
+ public Icon getKindIcon() {
+ String kind = getKind();
+ if (kind.contains("java")) {
+ return Icons.KIND_JAVA;
+ } else if (kind.contains("nodejs")) {
+ return Icons.KIND_JS;
+ } else if (kind.contains("python")) {
+ return Icons.KIND_PYTHON;
+ } else if (kind.contains("swift")) {
+ return Icons.KIND_SWIFT;
+ } else if (kind.contains("php")) {
+ return Icons.KIND_PHP;
+ } else if (kind.contains("go")) {
+ return Icons.KIND_GO;
+ } else if (kind.contains("ruby")) {
+ return Icons.KIND_RUBY;
+ } else if (kind.contains("sequence")) {
+ return Icons.KIND_SEQUENCE;
+ } else {
+ return Icons.KIND_DOCKER;
+ }
+ }
+
+
+ public boolean isSequenceAction() {
+ String kind = getKind();
+ return kind.equals("sequence");
+ }
+
+ public boolean isWebAction() {
+ for (Map<String, Object> a : this.annotations) {
+ if ("web-export".equals(a.get("key"))) {
+ return (Boolean) a.get("value");
+ }
+ }
+ return false;
+ }
+
+ public boolean isCustomOptions() {
+ for (Map<String, Object> a : this.annotations) {
+ if ("web-custom-options".equals(a.get("key"))) {
+ return (Boolean) a.get("value");
+ }
+ }
+ return false;
+ }
+
+ public boolean isRawHttp() {
+ for (Map<String, Object> a : this.annotations) {
+ if ("raw-http".equals(a.get("key"))) {
+ return (Boolean) a.get("value");
+ }
+ }
+ return false;
+ }
+
+ public boolean isFinalDefaultParameter() {
+ for (Map<String, Object> a : this.annotations) {
+ if ("final".equals(a.get("key"))) {
+ return (Boolean) a.get("value");
+ }
+ }
+ return false;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public long getUpdated() {
+ return updated;
+ }
+
+ public void setUpdated(long updated) {
+ this.updated = updated;
+ }
+
+ public boolean isPublish() {
+ return publish;
+ }
+
+ public void setPublish(boolean publish) {
+ this.publish = publish;
+ }
+
+ public List<Map<String, Object>> getAnnotations() {
+ return annotations;
+ }
+
+ public void setAnnotations(List<Map<String, Object>> annotations) {
+ this.annotations = annotations;
+ }
+
+ public Limits getLimits() {
+ return limits;
+ }
+
+ public void setLimits(Limits limits) {
+ this.limits = limits;
+ }
+
+ public E getExec() {
+ return exec;
+ }
+
+ public void setExec(E exec) {
+ this.exec = exec;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ WhiskAction<?> that = (WhiskAction<?>) o;
+
+ if (updated != that.updated) return false;
+ if (publish != that.publish) return false;
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false;
+ if (version != null ? !version.equals(that.version) : that.version != null) return false;
+ if (annotations != null ? !annotations.equals(that.annotations) : that.annotations != null) return false;
+ if (limits != null ? !limits.equals(that.limits) : that.limits != null) return false;
+ return exec != null ? exec.equals(that.exec) : that.exec == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
+ result = 31 * result + (version != null ? version.hashCode() : 0);
+ result = 31 * result + (int) (updated ^ (updated >>> 32));
+ result = 31 * result + (publish ? 1 : 0);
+ result = 31 * result + (annotations != null ? annotations.hashCode() : 0);
+ result = 31 * result + (limits != null ? limits.hashCode() : 0);
+ result = 31 * result + (exec != null ? exec.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/WhiskActionMetaData.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/WhiskActionMetaData.java
new file mode 100644
index 0000000..674995e
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/action/WhiskActionMetaData.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.action;
+
+import com.navercorp.openwhisk.intellij.common.whisk.model.Limits;
+import com.navercorp.openwhisk.intellij.common.whisk.model.exec.ExecMetaData;
+import com.navercorp.openwhisk.intellij.explorer.editor.model.ComboBoxEntityEntry;
+import com.navercorp.openwhisk.intellij.explorer.editor.model.ComboBoxEntityType;
+
+import java.util.List;
+import java.util.Map;
+
+public class WhiskActionMetaData extends WhiskAction<ExecMetaData> {
+ public WhiskActionMetaData() {
+ }
+
+ public WhiskActionMetaData(String name, String namespace, String version, long updated, boolean publish,
+ List<Map<String, Object>> annotations,
+ Limits limits,
+ ExecMetaData exec) {
+ super(name, namespace, version, updated, publish, annotations, limits, exec);
+ }
+
+ @Override
+ public String toString() {
+ return getWhiskPackage().map(pkg -> pkg + "/" + getName()).orElse(getName());
+ }
+
+ public ComboBoxEntityEntry toCombBoxEntityEntry() {
+ return new ComboBoxEntityEntry(toString(), ComboBoxEntityType.ACTION);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivation.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivation.java
new file mode 100644
index 0000000..4c0be99
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivation.java
@@ -0,0 +1,183 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.activation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public abstract class WhiskActivation {
+
+ private String activationId;
+ private String name;
+ private String namespace;
+ private String version;
+ private String cause;
+ private long start;
+ private long end;
+ private long duration;
+ private boolean publish;
+ private List<Map<String, Object>> annotations = new ArrayList<>();
+
+ public WhiskActivation() {
+ }
+
+ public WhiskActivation(String activationId, String name, String namespace, String version, String cause,
+ long start, long end, long duration, boolean publish,
+ List<Map<String, Object>> annotations) {
+ this.activationId = activationId;
+ this.name = name;
+ this.namespace = namespace;
+ this.version = version;
+ this.cause = cause;
+ this.start = start;
+ this.end = end;
+ this.duration = duration;
+ this.publish = publish;
+ this.annotations = annotations;
+ }
+
+ public String getActivationId() {
+ return activationId;
+ }
+
+ public void setActivationId(String activationId) {
+ this.activationId = activationId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getCause() {
+ return cause;
+ }
+
+ public void setCause(String cause) {
+ this.cause = cause;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public long getStart() {
+ return start;
+ }
+
+ public void setStart(long start) {
+ this.start = start;
+ }
+
+ public long getEnd() {
+ return end;
+ }
+
+ public void setEnd(long end) {
+ this.end = end;
+ }
+
+ public long getDuration() {
+ return duration;
+ }
+
+ public void setDuration(long duration) {
+ this.duration = duration;
+ }
+
+ public boolean isPublish() {
+ return publish;
+ }
+
+ public void setPublish(boolean publish) {
+ this.publish = publish;
+ }
+
+ public List<Map<String, Object>> getAnnotations() {
+ return annotations;
+ }
+
+ public void setAnnotations(List<Map<String, Object>> annotations) {
+ this.annotations = annotations;
+ }
+
+ public String getKind() {
+ for (Map<String, Object> a : annotations) {
+ if (a.get("key").equals("kind")) {
+ return (String) a.get("value");
+ }
+ }
+ return "unknown";
+ }
+
+ public String getStartType() {
+ for (Map<String, Object> a : annotations) {
+ if (a.get("key").equals("initTime")) {
+ return "cold";
+ }
+ }
+ return "warm";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ WhiskActivation that = (WhiskActivation) o;
+
+ if (start != that.start) return false;
+ if (end != that.end) return false;
+ if (duration != that.duration) return false;
+ if (publish != that.publish) return false;
+ if (activationId != null ? !activationId.equals(that.activationId) : that.activationId != null) return false;
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false;
+ if (version != null ? !version.equals(that.version) : that.version != null) return false;
+ return annotations != null ? annotations.equals(that.annotations) : that.annotations == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = activationId != null ? activationId.hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
+ result = 31 * result + (version != null ? version.hashCode() : 0);
+ result = 31 * result + (int) (start ^ (start >>> 32));
+ result = 31 * result + (int) (end ^ (end >>> 32));
+ result = 31 * result + (int) (duration ^ (duration >>> 32));
+ result = 31 * result + (publish ? 1 : 0);
+ result = 31 * result + (annotations != null ? annotations.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivationMetaData.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivationMetaData.java
new file mode 100644
index 0000000..9c210a1
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivationMetaData.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.activation;
+
+import java.util.List;
+import java.util.Map;
+
+public class WhiskActivationMetaData extends WhiskActivation {
+
+ private int statusCode;
+
+ public WhiskActivationMetaData() {
+ }
+
+ public WhiskActivationMetaData(String activationId, String name, String namespace, String version, String cause,
+ long start, long end, long duration, boolean publish,
+ List<Map<String, Object>> annotations,
+ int statusCode) {
+ super(activationId, name, namespace, version, cause, start, end, duration, publish, annotations);
+ this.statusCode = statusCode;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getStatus() {
+ switch (this.statusCode) {
+ case 0:
+ return "success";
+ case 1:
+ return "application error";
+ case 2:
+ return "developer error";
+ default:
+ return "internal error";
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ WhiskActivationMetaData that = (WhiskActivationMetaData) o;
+
+ return statusCode == that.statusCode;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + statusCode;
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivationWithLogs.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivationWithLogs.java
new file mode 100644
index 0000000..b780b6f
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/activation/WhiskActivationWithLogs.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.activation;
+
+import org.codehaus.groovy.util.ListHashMap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class WhiskActivationWithLogs extends WhiskActivation {
+ private String subject;
+ private List<String> logs = new ArrayList<>();
+ private Map<String, Object> response = new ListHashMap<>();
+
+ public WhiskActivationWithLogs() {
+ }
+
+ public WhiskActivationWithLogs(String activationId, String name, String namespace, String version, String cause,
+ long start, long end, long duration, boolean publish,
+ List<Map<String, Object>> annotations,
+ String subject,
+ List<String> logs,
+ Map<String, Object> response) {
+ super(activationId, name, namespace, version, cause, start, end, duration, publish, annotations);
+ this.subject = subject;
+ this.logs = logs;
+ this.response = response;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public void setSubject(String subject) {
+ this.subject = subject;
+ }
+
+ public List<String> getLogs() {
+ return logs;
+ }
+
+ public void setLogs(List<String> logs) {
+ this.logs = logs;
+ }
+
+ public Map<String, Object> getResponse() {
+ return response;
+ }
+
+ public void setResponse(Map<String, Object> response) {
+ this.response = response;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ WhiskActivationWithLogs that = (WhiskActivationWithLogs) o;
+
+ if (subject != null ? !subject.equals(that.subject) : that.subject != null) return false;
+ if (logs != null ? !logs.equals(that.logs) : that.logs != null) return false;
+ return response != null ? response.equals(that.response) : that.response == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (subject != null ? subject.hashCode() : 0);
+ result = 31 * result + (logs != null ? logs.hashCode() : 0);
+ result = 31 * result + (response != null ? response.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/CodeExec.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/CodeExec.java
new file mode 100644
index 0000000..1d4788b
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/CodeExec.java
@@ -0,0 +1,121 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.exec;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CodeExec extends Exec {
+ private String kind;
+ @Nullable
+ private String main;
+ private String code;
+ private String image; // for docker image
+ private List<String> components = new ArrayList<>(); // for sequence action
+
+ public CodeExec() {
+ }
+
+ public CodeExec(String kind, @Nullable String main, String code, String image, List<String> components) {
+ this.kind = kind;
+ this.main = main;
+ this.code = code;
+ this.image = image;
+ this.components = components;
+ }
+
+ public CodeExec(boolean binary, String kind, @Nullable String main, String code, String image, List<String> components) {
+ super(binary);
+ this.kind = kind;
+ this.main = main;
+ this.code = code;
+ this.image = image;
+ this.components = components;
+ }
+
+ public String getKind() {
+ return kind;
+ }
+
+ public void setKind(String kind) {
+ this.kind = kind;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getMain() {
+ return main;
+ }
+
+ public void setMain(String main) {
+ this.main = main;
+ }
+
+ public String getImage() {
+ return image;
+ }
+
+ public void setImage(String image) {
+ this.image = image;
+ }
+
+ public List<String> getComponents() {
+ return components;
+ }
+
+ public void setComponents(List<String> components) {
+ this.components = components;
+ }
+
+ public ExecMetaData toExecMetaData() {
+ return new ExecMetaData(isBinary());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ CodeExec codeExec = (CodeExec) o;
+
+ if (kind != null ? !kind.equals(codeExec.kind) : codeExec.kind != null) return false;
+ if (main != null ? !main.equals(codeExec.main) : codeExec.main != null) return false;
+ if (code != null ? !code.equals(codeExec.code) : codeExec.code != null) return false;
+ if (image != null ? !image.equals(codeExec.image) : codeExec.image != null) return false;
+ return components != null ? components.equals(codeExec.components) : codeExec.components == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (kind != null ? kind.hashCode() : 0);
+ result = 31 * result + (main != null ? main.hashCode() : 0);
+ result = 31 * result + (code != null ? code.hashCode() : 0);
+ result = 31 * result + (image != null ? image.hashCode() : 0);
+ result = 31 * result + (components != null ? components.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/CodeExecSerializer.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/CodeExecSerializer.java
new file mode 100644
index 0000000..c7072ec
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/CodeExecSerializer.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.exec;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+import java.util.Optional;
+
+public class CodeExecSerializer extends JsonSerializer<CodeExec> {
+ @Override
+ public void serialize(CodeExec codeExec, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+ jsonGenerator.writeStartObject();
+
+ jsonGenerator.writeFieldName("binary");
+ jsonGenerator.writeBoolean(codeExec.isBinary());
+
+ jsonGenerator.writeFieldName("kind");
+ jsonGenerator.writeString(codeExec.getKind());
+
+ if (Optional.ofNullable(codeExec.getCode()).isPresent()) {
+ jsonGenerator.writeFieldName("code");
+ jsonGenerator.writeString(codeExec.getCode());
+ }
+
+ if (Optional.ofNullable(codeExec.getMain()).isPresent()) {
+ jsonGenerator.writeFieldName("main");
+ jsonGenerator.writeString(codeExec.getMain());
+ }
+
+ if (Optional.ofNullable(codeExec.getImage()).isPresent()) {
+ jsonGenerator.writeFieldName("image");
+ jsonGenerator.writeString(codeExec.getImage());
+ }
+
+ if (!codeExec.getComponents().isEmpty()) {
+ jsonGenerator.writeFieldName("components");
+ jsonGenerator.writeStartArray();
+ for (String c : codeExec.getComponents()) {
+ jsonGenerator.writeString(c);
+ }
+ jsonGenerator.writeEndArray();
+ }
+
+ jsonGenerator.writeEndObject();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/Exec.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/Exec.java
new file mode 100644
index 0000000..2e48fb5
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/Exec.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.exec;
+
+public abstract class Exec {
+ private boolean binary;
+
+ public Exec() {
+ }
+
+ public Exec(boolean binary) {
+ this.binary = binary;
+ }
+
+
+ public boolean isBinary() {
+ return binary;
+ }
+
+ public void setBinary(boolean binary) {
+ this.binary = binary;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Exec exec = (Exec) o;
+
+ return binary == exec.binary;
+ }
+
+ @Override
+ public int hashCode() {
+ return (binary ? 1 : 0);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/ExecMetaData.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/ExecMetaData.java
new file mode 100644
index 0000000..6a11506
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/exec/ExecMetaData.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.exec;
+
+public class ExecMetaData extends Exec {
+ public ExecMetaData() {
+ }
+
+ public ExecMetaData(boolean binary) {
+ super(binary);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/pkg/WhiskPackage.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/pkg/WhiskPackage.java
new file mode 100644
index 0000000..41a7680
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/pkg/WhiskPackage.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.pkg;
+
+import com.navercorp.openwhisk.intellij.common.whisk.model.Binding;
+
+import java.util.*;
+
+public class WhiskPackage {
+ private String name;
+ private String namespace;
+ private boolean publish;
+ private long updated;
+ private String version;
+ private List<Map<String, Object>> annotations = new ArrayList<>();
+ private Object binding;
+
+ public WhiskPackage() {
+ }
+
+ public WhiskPackage(String name, String namespace, boolean publish, long updated, String version, List<Map<String, Object>> annotations, Object binding) {
+ this.name = name;
+ this.namespace = namespace;
+ this.publish = publish;
+ this.updated = updated;
+ this.version = version;
+ this.annotations = annotations;
+ this.binding = binding;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public boolean isPublish() {
+ return publish;
+ }
+
+ public void setPublish(boolean publish) {
+ this.publish = publish;
+ }
+
+ public long getUpdated() {
+ return updated;
+ }
+
+ public void setUpdated(long updated) {
+ this.updated = updated;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public List<Map<String, Object>> getAnnotations() {
+ return annotations;
+ }
+
+ public void setAnnotations(List<Map<String, Object>> annotations) {
+ this.annotations = annotations;
+ }
+
+ public Optional<Binding> getBinding() {
+ if (binding instanceof Map) {
+ Map<String, String> b = (LinkedHashMap) binding;
+ if (b.containsKey("namespace") && b.containsKey("name")) {
+ return Optional.of(new Binding(b.get("namespace"), b.get("name")));
+ } else {
+ return Optional.empty();
+ }
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ public void setBinding(Object binding) {
+ this.binding = binding;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ WhiskPackage that = (WhiskPackage) o;
+
+ if (publish != that.publish) return false;
+ if (updated != that.updated) return false;
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false;
+ if (version != null ? !version.equals(that.version) : that.version != null) return false;
+ if (annotations != null ? !annotations.equals(that.annotations) : that.annotations != null) return false;
+ return binding != null ? binding.equals(that.binding) : that.binding == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
+ result = 31 * result + (publish ? 1 : 0);
+ result = 31 * result + (int) (updated ^ (updated >>> 32));
+ result = 31 * result + (version != null ? version.hashCode() : 0);
+ result = 31 * result + (annotations != null ? annotations.hashCode() : 0);
+ result = 31 * result + (binding != null ? binding.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/pkg/WhiskPackageWithActions.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/pkg/WhiskPackageWithActions.java
new file mode 100644
index 0000000..5b547da
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/pkg/WhiskPackageWithActions.java
@@ -0,0 +1,92 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.pkg;
+
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.CompactWhiskAction;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class WhiskPackageWithActions extends WhiskPackage {
+
+ private List<Map<String, Object>> parameters = new ArrayList<>();
+ private List<CompactWhiskAction> actions = new ArrayList<>();
+ private List<Object> feeds = new ArrayList<>();
+
+ public WhiskPackageWithActions() {
+ }
+
+ public WhiskPackageWithActions(String name, String namespace, boolean publish, long updated, String version,
+ List<Map<String, Object>> annotations,
+ Object binding,
+ List<Map<String, Object>> parameters,
+ List<CompactWhiskAction> actions,
+ List<Object> feeds) {
+ super(name, namespace, publish, updated, version, annotations, binding);
+ this.parameters = parameters;
+ this.actions = actions;
+ this.feeds = feeds;
+ }
+
+ public List<CompactWhiskAction> getActions() {
+ return actions;
+ }
+
+ public void setActions(List<CompactWhiskAction> actions) {
+ this.actions = actions;
+ }
+
+ public List<Map<String, Object>> getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(List<Map<String, Object>> parameters) {
+ this.parameters = parameters;
+ }
+
+
+ public List<Object> getFeeds() {
+ return feeds;
+ }
+
+ public void setFeeds(List<Object> feeds) {
+ this.feeds = feeds;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ WhiskPackageWithActions that = (WhiskPackageWithActions) o;
+
+ if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false;
+ if (actions != null ? !actions.equals(that.actions) : that.actions != null) return false;
+ return feeds != null ? feeds.equals(that.feeds) : that.feeds == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
+ result = 31 * result + (actions != null ? actions.hashCode() : 0);
+ result = 31 * result + (feeds != null ? feeds.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/ExecutableWhiskTrigger.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/ExecutableWhiskTrigger.java
new file mode 100644
index 0000000..e9c9fae
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/ExecutableWhiskTrigger.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.trigger;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class ExecutableWhiskTrigger extends WhiskTrigger {
+
+ private List<Map<String, Object>> parameters = new ArrayList<>();
+ private Map<String, SimplifiedWhiskRule> rules = new LinkedHashMap<>();
+
+ /**
+ * Limits on a specific trigger. None yet.
+ */
+ private Map<String, Object> limits;
+
+ public ExecutableWhiskTrigger() {
+ }
+
+ public ExecutableWhiskTrigger(String name, String namespace, String version, long updated, boolean publish,
+ List<Map<String, Object>> annotations,
+ List<Map<String, Object>> parameters,
+ Map<String, SimplifiedWhiskRule> rules,
+ Map<String, Object> limits) {
+ super(name, namespace, version, updated, publish, annotations);
+ this.parameters = parameters;
+ this.rules = rules;
+ this.limits = limits;
+ }
+
+ public List<Map<String, Object>> getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(List<Map<String, Object>> parameters) {
+ this.parameters = parameters;
+ }
+
+ public Map<String, SimplifiedWhiskRule> getRules() {
+ return rules;
+ }
+
+ public void setRules(Map<String, SimplifiedWhiskRule> rules) {
+ this.rules = rules;
+ }
+
+ public Map<String, Object> getLimits() {
+ return limits;
+ }
+
+ public void setLimits(Map<String, Object> limits) {
+ this.limits = limits;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ ExecutableWhiskTrigger that = (ExecutableWhiskTrigger) o;
+
+ if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false;
+ if (rules != null ? !rules.equals(that.rules) : that.rules != null) return false;
+ return limits != null ? limits.equals(that.limits) : that.limits == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (parameters != null ? parameters.hashCode() : 0);
+ result = 31 * result + (rules != null ? rules.hashCode() : 0);
+ result = 31 * result + (limits != null ? limits.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/SimplifiedEntityMetaData.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/SimplifiedEntityMetaData.java
new file mode 100644
index 0000000..6ce3ed5
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/SimplifiedEntityMetaData.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.trigger;
+
+public class SimplifiedEntityMetaData {
+ private String path;
+ private String name;
+
+ public SimplifiedEntityMetaData() {
+ }
+
+ public SimplifiedEntityMetaData(String path, String name) {
+ this.path = path;
+ this.name = name;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPkgActionName() {
+ String pkg = "";
+ if (path.contains("/")) {
+ pkg = path.split("/")[1] + "/";
+ }
+ return pkg + name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ SimplifiedEntityMetaData that = (SimplifiedEntityMetaData) o;
+
+ if (path != null ? !path.equals(that.path) : that.path != null) return false;
+ return name != null ? name.equals(that.name) : that.name == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = path != null ? path.hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/SimplifiedWhiskRule.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/SimplifiedWhiskRule.java
new file mode 100644
index 0000000..cb3a420
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/SimplifiedWhiskRule.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.trigger;
+
+public class SimplifiedWhiskRule {
+
+ private SimplifiedEntityMetaData action;
+ private String status;
+
+ public SimplifiedWhiskRule() {
+ }
+
+ public SimplifiedWhiskRule(SimplifiedEntityMetaData action, String status) {
+ this.action = action;
+ this.status = status;
+ }
+
+ public SimplifiedEntityMetaData getAction() {
+ return action;
+ }
+
+ public void setAction(SimplifiedEntityMetaData action) {
+ this.action = action;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ SimplifiedWhiskRule that = (SimplifiedWhiskRule) o;
+
+ if (action != null ? !action.equals(that.action) : that.action != null) return false;
+ return status != null ? status.equals(that.status) : that.status == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = action != null ? action.hashCode() : 0;
+ result = 31 * result + (status != null ? status.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskRule.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskRule.java
new file mode 100644
index 0000000..5b57f94
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskRule.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.trigger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class WhiskRule extends WhiskRuleMetaData {
+
+ private String status;
+ private List<Map<String, Object>> annotations = new ArrayList<>();
+
+ public WhiskRule() {
+ }
+
+ public WhiskRule(String name, String namespace, String version, long updated, boolean publish,
+ SimplifiedEntityMetaData action, SimplifiedEntityMetaData trigger) {
+ super(name, namespace, version, updated, publish, action, trigger);
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public List<Map<String, Object>> getAnnotations() {
+ return annotations;
+ }
+
+ public void setAnnotations(List<Map<String, Object>> annotations) {
+ this.annotations = annotations;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ WhiskRule whiskRule = (WhiskRule) o;
+
+ if (status != null ? !status.equals(whiskRule.status) : whiskRule.status != null) return false;
+ return annotations != null ? annotations.equals(whiskRule.annotations) : whiskRule.annotations == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (status != null ? status.hashCode() : 0);
+ result = 31 * result + (annotations != null ? annotations.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskRuleMetaData.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskRuleMetaData.java
new file mode 100644
index 0000000..6c92016
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskRuleMetaData.java
@@ -0,0 +1,126 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.trigger;
+
+public class WhiskRuleMetaData {
+
+ private String name;
+ private String namespace;
+ private String version;
+ private long updated;
+ private boolean publish;
+ private SimplifiedEntityMetaData action;
+ private SimplifiedEntityMetaData trigger;
+
+ public WhiskRuleMetaData() {
+ }
+
+ public WhiskRuleMetaData(String name, String namespace, String version, long updated, boolean publish,
+ SimplifiedEntityMetaData action, SimplifiedEntityMetaData trigger) {
+ this.name = name;
+ this.namespace = namespace;
+ this.version = version;
+ this.updated = updated;
+ this.publish = publish;
+ this.action = action;
+ this.trigger = trigger;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public long getUpdated() {
+ return updated;
+ }
+
+ public void setUpdated(long updated) {
+ this.updated = updated;
+ }
+
+ public boolean isPublish() {
+ return publish;
+ }
+
+ public void setPublish(boolean publish) {
+ this.publish = publish;
+ }
+
+ public SimplifiedEntityMetaData getAction() {
+ return action;
+ }
+
+ public void setAction(SimplifiedEntityMetaData action) {
+ this.action = action;
+ }
+
+ public SimplifiedEntityMetaData getTrigger() {
+ return trigger;
+ }
+
+ public void setTrigger(SimplifiedEntityMetaData trigger) {
+ this.trigger = trigger;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ WhiskRuleMetaData whiskRuleMetaData = (WhiskRuleMetaData) o;
+
+ if (updated != whiskRuleMetaData.updated) return false;
+ if (publish != whiskRuleMetaData.publish) return false;
+ if (name != null ? !name.equals(whiskRuleMetaData.name) : whiskRuleMetaData.name != null) return false;
+ if (namespace != null ? !namespace.equals(whiskRuleMetaData.namespace) : whiskRuleMetaData.namespace != null) return false;
+ if (version != null ? !version.equals(whiskRuleMetaData.version) : whiskRuleMetaData.version != null) return false;
+ if (action != null ? !action.equals(whiskRuleMetaData.action) : whiskRuleMetaData.action != null) return false;
+ return trigger != null ? trigger.equals(whiskRuleMetaData.trigger) : whiskRuleMetaData.trigger == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
+ result = 31 * result + (version != null ? version.hashCode() : 0);
+ result = 31 * result + (int) (updated ^ (updated >>> 32));
+ result = 31 * result + (publish ? 1 : 0);
+ result = 31 * result + (action != null ? action.hashCode() : 0);
+ result = 31 * result + (trigger != null ? trigger.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTrigger.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTrigger.java
new file mode 100644
index 0000000..8063521
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTrigger.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.trigger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public abstract class WhiskTrigger {
+
+ private String name;
+ private String namespace;
+ private String version;
+ private long updated;
+ private boolean publish;
+ private List<Map<String, Object>> annotations = new ArrayList<>();
+
+ public WhiskTrigger() {
+ }
+
+ public WhiskTrigger(String name, String namespace, String version, long updated, boolean publish, List<Map<String, Object>> annotations) {
+ this.name = name;
+ this.namespace = namespace;
+ this.version = version;
+ this.updated = updated;
+ this.publish = publish;
+ this.annotations = annotations;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public long getUpdated() {
+ return updated;
+ }
+
+ public void setUpdated(long updated) {
+ this.updated = updated;
+ }
+
+ public boolean isPublish() {
+ return publish;
+ }
+
+ public void setPublish(boolean publish) {
+ this.publish = publish;
+ }
+
+ public List<Map<String, Object>> getAnnotations() {
+ return annotations;
+ }
+
+ public void setAnnotations(List<Map<String, Object>> annotations) {
+ this.annotations = annotations;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ WhiskTrigger that = (WhiskTrigger) o;
+
+ if (updated != that.updated) return false;
+ if (publish != that.publish) return false;
+ if (name != null ? !name.equals(that.name) : that.name != null) return false;
+ if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false;
+ if (version != null ? !version.equals(that.version) : that.version != null) return false;
+ return annotations != null ? annotations.equals(that.annotations) : that.annotations == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
+ result = 31 * result + (version != null ? version.hashCode() : 0);
+ result = 31 * result + (int) (updated ^ (updated >>> 32));
+ result = 31 * result + (publish ? 1 : 0);
+ result = 31 * result + (annotations != null ? annotations.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTriggerMetaData.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTriggerMetaData.java
new file mode 100644
index 0000000..a5250b4
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTriggerMetaData.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.trigger;
+
+import com.navercorp.openwhisk.intellij.explorer.editor.model.ComboBoxEntityEntry;
+import com.navercorp.openwhisk.intellij.explorer.editor.model.ComboBoxEntityType;
+
+import java.util.List;
+import java.util.Map;
+
+public class WhiskTriggerMetaData extends WhiskTrigger {
+
+ public WhiskTriggerMetaData() {
+ }
+
+ public WhiskTriggerMetaData(String name, String namespace, String version, long updated, boolean publish, List<Map<String, Object>> annotations) {
+ super(name, namespace, version, updated, publish, annotations);
+ }
+
+ public ComboBoxEntityEntry toCombBoxEntityEntry() {
+ return new ComboBoxEntityEntry(getName(), ComboBoxEntityType.TRIGGER);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTriggerRoot.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTriggerRoot.java
new file mode 100644
index 0000000..be28a78
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/trigger/WhiskTriggerRoot.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.trigger;
+
+public class WhiskTriggerRoot {
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/NullWskDeployBinary.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/NullWskDeployBinary.java
new file mode 100644
index 0000000..32bd8e1
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/NullWskDeployBinary.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy;
+
+public class NullWskDeployBinary implements WskDeployFile {
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployBinary.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployBinary.java
new file mode 100644
index 0000000..86062d5
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployBinary.java
@@ -0,0 +1,43 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy;
+
+public class WskDeployBinary implements WskDeployFile {
+ private String fullPath;
+ private String name;
+
+ public WskDeployBinary(String fullPath, String name) {
+ this.fullPath = fullPath;
+ this.name = name;
+ }
+
+ public String getFullPath() {
+ return fullPath;
+ }
+
+ public void setFullPath(String fullPath) {
+ this.fullPath = fullPath;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmd.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmd.java
new file mode 100644
index 0000000..8c3db12
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmd.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy;
+
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+
+public interface WskDeployCmd {
+
+ String[] toCmd(WhiskAuth auth);
+
+ String toCmdString();
+
+ String getCmdName();
+
+ WskDeployManifest getManifest();
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdDeploy.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdDeploy.java
new file mode 100644
index 0000000..daf0463
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdDeploy.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy;
+
+import com.navercorp.openwhisk.intellij.common.error.NotExistFileException;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+
+import java.util.Optional;
+
+public class WskDeployCmdDeploy implements WskDeployCmd {
+
+ private Optional<WskDeployBinary> wskDeployBinary;
+ private WskDeployManifest manifest;
+
+ private WskDeployCmdDeploy() {
+ }
+
+ public WskDeployCmdDeploy(Optional<WskDeployBinary> wskDeployBinary, WskDeployManifest manifest) {
+ this.wskDeployBinary = wskDeployBinary;
+ this.manifest = manifest;
+ }
+
+ @Override
+ public String[] toCmd(WhiskAuth auth) {
+ return wskDeployBinary
+ .map(bin -> new String[]{
+ bin.getFullPath(),
+ "--manifest", manifest.getFullPath(),
+ "--auth", auth.getAuth(),
+ "--apihost", auth.getApihost()
+ })
+ .orElseThrow(() -> new NotExistFileException("The wskdeploy binary file does not exist."));
+ }
+
+ @Override
+ public String toCmdString() {
+ String[] cmd = wskDeployBinary
+ .map(bin -> new String[]{
+ bin.getFullPath(),
+ "--manifest", manifest.getFullPath(),
+ })
+ .orElseThrow(() -> new NotExistFileException("The wskdeploy binary file does not exist."));
+ StringBuilder str = new StringBuilder();
+ for (String c : cmd) {
+ str.append(c + " ");
+ }
+ return str.toString();
+ }
+
+ @Override
+ public String getCmdName() {
+ return "deploy";
+ }
+
+ @Override
+ public WskDeployManifest getManifest() {
+ return manifest;
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdResponse.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdResponse.java
new file mode 100644
index 0000000..6ccdb3b
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdResponse.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy;
+
+public class WskDeployCmdResponse {
+ private int existCode;
+ private String successOutput;
+ private String errorOutput;
+
+ public WskDeployCmdResponse(int existCode, String successOutput, String errorOutput) {
+ this.existCode = existCode;
+ this.successOutput = successOutput;
+ this.errorOutput = errorOutput;
+ }
+
+ public int getExistCode() {
+ return existCode;
+ }
+
+ public void setExistCode(int existCode) {
+ this.existCode = existCode;
+ }
+
+ public String getSuccessOutput() {
+ return successOutput;
+ }
+
+ public void setSuccessOutput(String successOutput) {
+ this.successOutput = successOutput;
+ }
+
+ public String getErrorOutput() {
+ return errorOutput;
+ }
+
+ public void setErrorOutput(String errorOutput) {
+ this.errorOutput = errorOutput;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdUndeploy.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdUndeploy.java
new file mode 100644
index 0000000..d7a2d2b
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployCmdUndeploy.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy;
+
+import com.navercorp.openwhisk.intellij.common.error.NotExistFileException;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+
+import java.util.Optional;
+
+public class WskDeployCmdUndeploy implements WskDeployCmd {
+
+ private Optional<WskDeployBinary> wskDeployBinary;
+ private WskDeployManifest manifest;
+
+ private WskDeployCmdUndeploy() {
+ }
+
+ public WskDeployCmdUndeploy(Optional<WskDeployBinary> wskDeployBinary, WskDeployManifest manifest) {
+ this.wskDeployBinary = wskDeployBinary;
+ this.manifest = manifest;
+ }
+
+ @Override
+ public String[] toCmd(WhiskAuth auth) {
+ return wskDeployBinary
+ .map(bin -> new String[]{
+ bin.getFullPath(), "undeploy",
+ "--manifest", manifest.getFullPath(),
+ "--auth", auth.getAuth(),
+ "--apihost", auth.getApihost()
+ })
+ .orElseThrow(() -> new NotExistFileException("The wskdeploy binary file does not exist."));
+ }
+
+ @Override
+ public String toCmdString() throws NotExistFileException {
+ String[] cmd = wskDeployBinary
+ .map(bin -> new String[]{
+ bin.getFullPath(), "undeploy",
+ "--manifest", manifest.getFullPath(),
+ })
+ .orElseThrow(() -> new NotExistFileException("The wskdeploy binary file does not exist."));
+ StringBuilder str = new StringBuilder();
+ for (String c : cmd) {
+ str.append(c + " ");
+ }
+ return str.toString();
+ }
+
+ @Override
+ public String getCmdName() {
+ return "undeploy";
+ }
+
+ @Override
+ public WskDeployManifest getManifest() {
+ return manifest;
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployFile.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployFile.java
new file mode 100644
index 0000000..4b010c1
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployFile.java
@@ -0,0 +1,20 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy;
+
+public interface WskDeployFile {
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployManifest.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployManifest.java
new file mode 100644
index 0000000..8bc4b1f
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/model/wskdeploy/WskDeployManifest.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.model.wskdeploy;
+
+public class WskDeployManifest {
+
+ private String path;
+ private String fullPath;
+ private String name;
+
+ public WskDeployManifest() {
+ }
+
+ public WskDeployManifest(String filePath, String fullFilePath, String fileName) {
+ this.path = filePath;
+ this.fullPath = fullFilePath;
+ this.name = fileName;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getFullPath() {
+ return fullPath;
+ }
+
+ public void setFullPath(String fullPath) {
+ this.fullPath = fullPath;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ WskDeployManifest manifest = (WskDeployManifest) o;
+
+ if (path != null ? !path.equals(manifest.path) : manifest.path != null) return false;
+ if (fullPath != null ? !fullPath.equals(manifest.fullPath) : manifest.fullPath != null) return false;
+ return name != null ? name.equals(manifest.name) : manifest.name == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = path != null ? path.hashCode() : 0;
+ result = 31 * result + (fullPath != null ? fullPath.hashCode() : 0);
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskActionService.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskActionService.java
new file mode 100644
index 0000000..1bdfda4
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskActionService.java
@@ -0,0 +1,128 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.service;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.ExecutableWhiskAction;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.WhiskActionMetaData;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.fluent.Request;
+import org.apache.http.entity.ContentType;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class WhiskActionService {
+ private static final Logger LOG = Logger.getInstance(WhiskActionService.class);
+
+ private WhiskActionService() {
+
+ }
+
+ private static class LazyHolder {
+ private static final WhiskActionService INSTANCE = new WhiskActionService();
+ }
+
+ public static WhiskActionService getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ public List<WhiskActionMetaData> getWhiskActions(WhiskAuth whiskAuth) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/actions?limit=200&skip=0";
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskActions(result);
+ }
+
+ public Optional<ExecutableWhiskAction> getWhiskAction(WhiskAuth whiskAuth,
+ Optional<String> namespaceName,
+ Optional<String> pkgName,
+ String actionName) throws IOException {
+ String namespace = namespaceName.orElse("_");
+ String name = pkgName.map(p -> p + "/" + actionName).orElse(actionName);
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/" + namespace + "/actions/" + name + "?code=true";
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskAction(result);
+ }
+
+ public String invokeWhiskAction(WhiskAuth whiskAuth,
+ Optional<String> namespaceName,
+ Optional<String> pkgName,
+ String actionName,
+ String params) throws IOException {
+ String namespace = namespaceName.orElse("_");
+ String name = pkgName.map(p -> p + "/" + actionName).orElse(actionName);
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/" + namespace + "/actions/" + name + "?blocking=true&result=true";
+ String authorization = whiskAuth.getBasicAuthHeader();
+ String result = Request.Post(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .bodyString(params, ContentType.APPLICATION_JSON)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.beautifyJson(result);
+ }
+
+ public Optional<ExecutableWhiskAction> updateWhiskAction(WhiskAuth whiskAuth,
+ ExecutableWhiskAction updatedAction,
+ Map<String, Object> payload) throws IOException {
+ String namespace = updatedAction.getNamespacePath();
+ String name = updatedAction.getWhiskPackage().map(p -> p + "/" + updatedAction.getName()).orElse(updatedAction.getName());
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/" + namespace + "/actions/" + name + "?overwrite=true";
+ String authorization = whiskAuth.getBasicAuthHeader();
+ String body = JsonParserUtils.writeMapToJson(payload);
+ LOG.info("Action updated: " + body);
+ String result = Request.Put(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .bodyString(body, ContentType.APPLICATION_JSON)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskAction(result);
+ }
+
+ public Optional<ExecutableWhiskAction> deleteWhiskActions(WhiskAuth whiskAuth, Optional<String> pkgName, String actionName) throws IOException {
+ String name = pkgName.map(p -> p + "/" + actionName).orElse(actionName);
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/actions/" + name;
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Delete(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskAction(result);
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskActivationService.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskActivationService.java
new file mode 100644
index 0000000..c3b1ac5
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskActivationService.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.service;
+
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.activation.WhiskActivationMetaData;
+import com.navercorp.openwhisk.intellij.common.whisk.model.activation.WhiskActivationWithLogs;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.fluent.Request;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class WhiskActivationService {
+
+ private WhiskActivationService() {
+ }
+
+ private static class LazyHolder {
+ private static final WhiskActivationService INSTANCE = new WhiskActivationService();
+ }
+
+ public static WhiskActivationService getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ public List<WhiskActivationMetaData> getWhiskActivations(WhiskAuth whiskAuth, Optional<String> name, int limit, int skip) throws IOException {
+ String endpoint = whiskAuth.getApihost()
+ + "/api/v1/namespaces/_/activations"
+ + "?limit=" + limit + "&skip=" + skip + "" + name.map(n -> "&name=" + n).orElse("");
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskActivations(result);
+ }
+
+ public Optional<WhiskActivationWithLogs> getWhiskActivation(WhiskAuth whiskAuth, String activationId) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/activations/" + activationId;
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskActivation(result);
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskNamespaceService.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskNamespaceService.java
new file mode 100644
index 0000000..9621aa3
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskNamespaceService.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.service;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.fluent.Request;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskNamespace;
+
+import java.io.IOException;
+import java.util.Optional;
+
+public class WhiskNamespaceService {
+ private static final Logger LOG = Logger.getInstance(WhiskNamespaceService.class);
+
+ private WhiskNamespaceService() {
+
+ }
+
+ private static class LazyHolder {
+ private static final WhiskNamespaceService INSTANCE = new WhiskNamespaceService();
+ }
+
+ public static WhiskNamespaceService getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ public Optional<WhiskNamespace> validateNamespace(WhiskAuth whiskAuth) {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces";
+ String authorization = whiskAuth.getBasicAuthHeader();
+ try {
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString();
+
+ String[] namespaces = JsonParserUtils.parseWhiskNamespace(result);
+ if (namespaces.length > 0) {
+ return Optional.of(new WhiskNamespace(whiskAuth.getAuth(), namespaces[0]));
+ } else {
+ return Optional.empty();
+ }
+ } catch (IOException e) {
+ LOG.warn("Invalid namespace", e);
+ return Optional.empty();
+ }
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskPackageService.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskPackageService.java
new file mode 100644
index 0000000..f6702b5
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskPackageService.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.service;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.fluent.Request;
+import org.apache.http.entity.ContentType;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackage;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackageWithActions;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class WhiskPackageService {
+ private static final Logger LOG = Logger.getInstance(WhiskPackageService.class);
+
+ private WhiskPackageService() {
+
+ }
+
+ private static class LazyHolder {
+ private static final WhiskPackageService INSTANCE = new WhiskPackageService();
+ }
+
+ public static WhiskPackageService getInstance() {
+ return WhiskPackageService.LazyHolder.INSTANCE;
+ }
+
+ public List<WhiskPackage> getWhiskPackages(WhiskAuth whiskAuth) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/packages?limit=200&skip=0";
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskPackages(result);
+ }
+
+ public Optional<WhiskPackageWithActions> getWhiskPackage(WhiskAuth whiskAuth, String namespace, String name) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/" + namespace + "/packages/" + name;
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskPackage(result);
+ }
+
+ public Optional<WhiskPackageWithActions> deleteWhiskPackage(WhiskAuth whiskAuth, String name) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/packages/" + name;
+ String authorization = whiskAuth.getBasicAuthHeader();
+ HttpResponse response = Request.Delete(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnResponse();
+
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_CONFLICT) {
+ return Optional.empty();
+ } else {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ response.getEntity().getContent()));
+ String inputLine;
+ StringBuffer result = new StringBuffer();
+ while ((inputLine = reader.readLine()) != null) {
+ result.append(inputLine);
+ }
+ reader.close();
+ return JsonParserUtils.parseWhiskPackage(result.toString());
+ }
+ }
+
+ public Optional<WhiskPackageWithActions> updateWhiskPackage(WhiskAuth whiskAuth, String name, Map<String, Object> payload) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/packages/" + name + "?overwrite=true";
+ String authorization = whiskAuth.getBasicAuthHeader();
+ String body = JsonParserUtils.writeMapToJson(payload);
+ LOG.info("Package updated: " + body);
+ String result = Request.Put(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .bodyString(body, ContentType.APPLICATION_JSON)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskPackage(result);
+ }
+
+ public Optional<WhiskPackageWithActions> createWhiskPackage(WhiskAuth whiskAuth, String name, Map<String, Object> payload) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/packages/" + name + "?overwrite=false";
+ String authorization = whiskAuth.getBasicAuthHeader();
+ String body = JsonParserUtils.writeMapToJson(payload);
+ LOG.info("Package craeted: " + body);
+ HttpResponse response = Request.Put(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .bodyString(body, ContentType.APPLICATION_JSON)
+ .execute()
+ .returnResponse();
+
+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_CONFLICT) {
+ return Optional.empty();
+ } else {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ response.getEntity().getContent()));
+ String inputLine;
+ StringBuffer result = new StringBuffer();
+ while ((inputLine = reader.readLine()) != null) {
+ result.append(inputLine);
+ }
+ reader.close();
+ return JsonParserUtils.parseWhiskPackage(result.toString());
+ }
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskRuleService.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskRuleService.java
new file mode 100644
index 0000000..bc93ae5
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskRuleService.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.service;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.fluent.Request;
+import org.apache.http.entity.ContentType;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.trigger.WhiskRule;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Optional;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class WhiskRuleService {
+ private static final Logger LOG = Logger.getInstance(WhiskRuleService.class);
+
+ private WhiskRuleService() {
+ }
+
+ private static class LazyHolder {
+ private static final WhiskRuleService INSTANCE = new WhiskRuleService();
+ }
+
+ public static WhiskRuleService getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ public Optional<WhiskRule> updateWhiskRule(WhiskAuth whiskAuth, String ruleName, Map<String, Object> payload) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/rules/" + ruleName + "?overwrite=true";
+ String authorization = whiskAuth.getBasicAuthHeader();
+ String body = JsonParserUtils.writeMapToJson(payload);
+ LOG.info("Rule updated: " + body);
+ String result = Request.Put(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .bodyString(body, ContentType.APPLICATION_JSON)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskRule(result);
+ }
+
+ public Optional<WhiskRule> deleteWhiskRule(WhiskAuth whiskAuth, String ruleName) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/rules/" + ruleName;
+ String authorization = whiskAuth.getBasicAuthHeader();
+ String result = Request.Delete(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskRule(result);
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskTriggerService.java b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskTriggerService.java
new file mode 100644
index 0000000..4c3e095
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/common/whisk/service/WhiskTriggerService.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.common.whisk.service;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import org.apache.http.HttpHeaders;
+import org.apache.http.client.fluent.Content;
+import org.apache.http.client.fluent.Request;
+import org.apache.http.entity.ContentType;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.trigger.ExecutableWhiskTrigger;
+import com.navercorp.openwhisk.intellij.common.whisk.model.trigger.WhiskTriggerMetaData;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+public class WhiskTriggerService {
+ private static final Logger LOG = Logger.getInstance(WhiskTriggerService.class);
+
+ private WhiskTriggerService() {
+ }
+
+ private static class LazyHolder {
+ private static final WhiskTriggerService INSTANCE = new WhiskTriggerService();
+ }
+
+ public static WhiskTriggerService getInstance() {
+ return LazyHolder.INSTANCE;
+ }
+
+ public List<WhiskTriggerMetaData> getWhiskTriggers(WhiskAuth whiskAuth) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/triggers?limit=50&skip=0";
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskTriggers(result);
+ }
+
+ public Optional<ExecutableWhiskTrigger> getWhiskTrigger(WhiskAuth whiskAuth, String triggerName) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/triggers/" + triggerName;
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Get(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskTrigger(result);
+ }
+
+ public Optional<String> fireWhiskTrigger(WhiskAuth whiskAuth, String triggerName, String params) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/triggers/" + triggerName;
+ String authorization = whiskAuth.getBasicAuthHeader();
+ Content content = Request.Post(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .bodyString(params, ContentType.APPLICATION_JSON)
+ .execute()
+ .returnContent();
+ if (content != null) {
+ return Optional.ofNullable(JsonParserUtils.beautifyJson(content.asString(UTF_8)));
+ } else {
+ return Optional.empty();
+ }
+ }
+
+ public Optional<ExecutableWhiskTrigger> deleteWhiskTrigger(WhiskAuth whiskAuth, String triggerName) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/triggers/" + triggerName;
+ String authorization = whiskAuth.getBasicAuthHeader();
+
+ String result = Request.Delete(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskTrigger(result);
+ }
+
+ public Optional<ExecutableWhiskTrigger> createWhiskTrigger(WhiskAuth whiskAuth, String triggerName, Map<String, Object> payload) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/triggers/" + triggerName + "?overwrite=false";
+ String authorization = whiskAuth.getBasicAuthHeader();
+ String body = JsonParserUtils.writeMapToJson(payload);
+ LOG.info("Trigger updated: " + body);
+ String result = Request.Put(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .bodyString(body, ContentType.APPLICATION_JSON)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskTrigger(result);
+ }
+
+ public Optional<ExecutableWhiskTrigger> updateWhiskTrigger(WhiskAuth whiskAuth, String triggerName, Map<String, Object> payload) throws IOException {
+ String endpoint = whiskAuth.getApihost() + "/api/v1/namespaces/_/triggers/" + triggerName + "?overwrite=true";
+ String authorization = whiskAuth.getBasicAuthHeader();
+ String body = JsonParserUtils.writeMapToJson(payload);
+ LOG.info("Trigger updated: " + body);
+ String result = Request.Put(endpoint)
+ .setHeader(HttpHeaders.AUTHORIZATION, authorization)
+ .bodyString(body, ContentType.APPLICATION_JSON)
+ .execute()
+ .returnContent()
+ .asString(UTF_8);
+ return JsonParserUtils.parseWhiskTrigger(result);
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ActionManagerDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ActionManagerDialog.java
new file mode 100644
index 0000000..7a10e4b
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ActionManagerDialog.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action;
+
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.DialogWrapperWithApply;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.ExecutableWhiskAction;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.WhiskActionMetaData;
+import com.navercorp.openwhisk.intellij.explorer.dialog.action.ui.ActionManagerDialogForm;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.List;
+
+public class ActionManagerDialog extends DialogWrapperWithApply {
+
+ private ActionManagerDialogForm actionManagerDialogForm;
+
+ public ActionManagerDialog(Project project, WhiskAuth auth, ExecutableWhiskAction action, List<WhiskActionMetaData> actions) {
+ super(project, true); // use current window as parent
+ actionManagerDialogForm = new ActionManagerDialogForm(project, auth, action, actions);
+ setTitle("Manage Action");
+ setResizable(false);
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ if (actionManagerDialogForm != null) {
+ return this.actionManagerDialogForm.getContent();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected void doApplyAction() {
+ if (actionManagerDialogForm != null) {
+ actionManagerDialogForm.updateAction();
+ }
+ super.doApplyAction();
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (actionManagerDialogForm != null && !myApplyAction.isApplied()) {
+ actionManagerDialogForm.updateAction();
+ }
+ super.doOKAction();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/DeleteActionDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/DeleteActionDialog.java
new file mode 100644
index 0000000..bb510bb
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/DeleteActionDialog.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class DeleteActionDialog extends DialogWrapper {
+
+ public DeleteActionDialog(Project project) {
+ super(true); // use current window as parent
+ setTitle("Delete Action");
+ setResizable(false);
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ JPanel dialogPanel = new JPanel(new BorderLayout());
+
+ JLabel label = new JLabel("Are you sure you want to delete your action?");
+ label.setPreferredSize(new Dimension(100, 30));
+ dialogPanel.add(label, BorderLayout.CENTER);
+
+ return dialogPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/DownActionListener.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/DownActionListener.java
new file mode 100644
index 0000000..c3ca8ed
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/DownActionListener.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.listener;
+
+public interface DownActionListener {
+ void downAction(int index);
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/RemoveActionListener.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/RemoveActionListener.java
new file mode 100644
index 0000000..c211853
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/RemoveActionListener.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.listener;
+
+public interface RemoveActionListener {
+ void removeAction(int index);
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/UpActionListener.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/UpActionListener.java
new file mode 100644
index 0000000..32d88bc
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/listener/UpActionListener.java
@@ -0,0 +1,21 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.listener;
+
+public interface UpActionListener {
+ void upAction(int index);
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/ActionManagerDialogForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/ActionManagerDialogForm.form
new file mode 100644
index 0000000..9ecf0e0
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/ActionManagerDialogForm.form
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.action.ui.ActionManagerDialogForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="14" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="936" height="525"/>
+ </constraints>
+ <properties>
+ <preferredSize width="800" height="300"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <grid id="519e8" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="0">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="800" height="30"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="27de0" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Runtime"/>
+ </properties>
+ </component>
+ <component id="e5ddb" class="javax.swing.JComboBox" binding="runtimeJComboBox">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="4cbec" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="fd8b" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="0">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="800" height="30"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="10d33" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="47667" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Timeout (ms)"/>
+ </properties>
+ </component>
+ <component id="8ac53" class="javax.swing.JSpinner" binding="timeoutJSpinner">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="b5d2b" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="dd67a" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="866bd" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Memory (MB)"/>
+ </properties>
+ </component>
+ <component id="43f8a" class="javax.swing.JSpinner" binding="memoryJSpinner">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="6f7cf" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="19f4a" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="2e6c5" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="true" hgap="-1" vgap="0">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="1" use-parent-layout="false">
+ <minimum-size width="-1" height="30"/>
+ <preferred-size width="800" height="30"/>
+ <maximum-size width="-1" height="30"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="17e79" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="77c80" class="javax.swing.JCheckBox" binding="webactionJCheckBox">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="300" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Web Action"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="30b99" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="61458" class="javax.swing.JCheckBox" binding="rawHttpJCheckBox">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Raw HTTP"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="660f" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="d7b90" class="javax.swing.JCheckBox" binding="customOptionHeaderJCheckBox">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Custom Options Header"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="96f9d" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="ed717" class="javax.swing.JCheckBox" binding="finalOptionJCheckBox">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Protect Default Parameter"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ <grid id="4506f" binding="defaultParameterJPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="12" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ <component id="bc149" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="-1" height="5"/>
+ <maximum-size width="-1" height="5"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="f54d9" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="-1" height="5"/>
+ <maximum-size width="-1" height="5"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="ee953" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="-1" height="5"/>
+ <maximum-size width="-1" height="5"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="1ae9" class="javax.swing.JSeparator" binding="defaultParameterJSeparator">
+ <constraints>
+ <grid row="13" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="-1" height="5"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <grid id="82b18" binding="dockerImageJPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="8" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ <component id="7ff6e" class="javax.swing.JSeparator" binding="dockerImageJSeparator">
+ <constraints>
+ <grid row="9" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="-1" height="5"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <grid id="33dc2" binding="linkedActionsJPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="-1" height="150"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ <component id="c5701" class="javax.swing.JSeparator" binding="linkedActionsJSeparator">
+ <constraints>
+ <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <grid id="96812" binding="codeTypeJPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="10" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ <component id="4bebf" class="javax.swing.JSeparator" binding="codeTypeJSeparator">
+ <constraints>
+ <grid row="11" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/ActionManagerDialogForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/ActionManagerDialogForm.java
new file mode 100644
index 0000000..6f68c21
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/ActionManagerDialogForm.java
@@ -0,0 +1,413 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.ui;
+
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.uiDesigner.core.GridConstraints;
+import com.navercorp.openwhisk.intellij.common.notification.SimpleNotifier;
+import com.navercorp.openwhisk.intellij.common.utils.EventUtils;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import com.navercorp.openwhisk.intellij.common.utils.ParameterUtils;
+import com.navercorp.openwhisk.intellij.common.whisk.model.Limits;
+import com.navercorp.openwhisk.intellij.common.whisk.model.Runtime;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.ExecutableWhiskAction;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.WhiskActionMetaData;
+import com.navercorp.openwhisk.intellij.common.whisk.model.exec.CodeExec;
+import com.navercorp.openwhisk.intellij.common.whisk.service.WhiskActionService;
+import com.navercorp.openwhisk.intellij.explorer.toolwindow.listener.RefreshWhiskTreeListener;
+import com.navercorp.openwhisk.intellij.run.toolwindow.listener.RefreshActionOrTriggerListener;
+
+import javax.swing.*;
+import javax.swing.event.ListDataListener;
+import java.awt.*;
+import java.awt.event.ItemEvent;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static com.intellij.uiDesigner.core.GridConstraints.*;
+
+public class ActionManagerDialogForm {
+ private static final Logger LOG = Logger.getInstance(ActionManagerDialogForm.class);
+ private static final SimpleNotifier NOTIFIER = SimpleNotifier.getInstance();
+
+ private JPanel mainJPanel;
+ private JComboBox runtimeJComboBox;
+ private JCheckBox webactionJCheckBox;
+ private JCheckBox rawHttpJCheckBox;
+ private JCheckBox customOptionHeaderJCheckBox;
+ private JCheckBox finalOptionJCheckBox;
+ private JSpinner timeoutJSpinner;
+ private JSpinner memoryJSpinner;
+ private JPanel defaultParameterJPanel;
+ private JSeparator defaultParameterJSeparator;
+ private JPanel dockerImageJPanel;
+ private JSeparator dockerImageJSeparator;
+ private JPanel linkedActionsJPanel;
+ private JSeparator linkedActionsJSeparator;
+ private JSeparator codeTypeJSeparator;
+ private JPanel codeTypeJPanel;
+
+ private DefaultParameterForm defaultParameterForm;
+ private DockerImageForm dockerImageForm;
+ private CodeTypeForm codeTypeForm;
+ private LinkedActionsForm linkedActionsForm;
+
+ private Project project;
+ private WhiskAuth whiskAuth;
+ private ExecutableWhiskAction action;
+
+ private WhiskActionService whiskActionService = WhiskActionService.getInstance();
+
+ public ActionManagerDialogForm(Project project, WhiskAuth auth, ExecutableWhiskAction action, List<WhiskActionMetaData> actions) {
+ this.project = project;
+ this.whiskAuth = auth;
+ this.action = action;
+
+ // add linked actions panel
+ linkedActionsForm = new LinkedActionsForm(project, action.getNamespace().split("/")[0], actions, action.getExec().getComponents());
+ linkedActionsJPanel.add(linkedActionsForm.getContent(), BorderLayout.CENTER);
+
+ // add docker image panel
+ dockerImageForm = new DockerImageForm();
+ dockerImageJPanel.add(dockerImageForm.getContent(), BorderLayout.CENTER);
+
+ // add code type panel
+ codeTypeForm = new CodeTypeForm();
+ codeTypeJPanel.add(codeTypeForm.getContent(), BorderLayout.CENTER);
+
+ // add default parameter panel
+ defaultParameterForm = new DefaultParameterForm();
+ defaultParameterJPanel.add(defaultParameterForm.getContent(), BorderLayout.CENTER);
+
+ switch (action.getKind()) {
+ case "sequence":
+ // remove docker image panel
+ mainJPanel.remove(dockerImageJPanel);
+ mainJPanel.remove(dockerImageJSeparator);
+
+ // remove code type panel
+ mainJPanel.remove(codeTypeJPanel);
+ mainJPanel.remove(codeTypeJSeparator);
+
+ // remove default parameter panel
+ mainJPanel.remove(defaultParameterJPanel);
+ mainJPanel.remove(defaultParameterJSeparator);
+ break;
+ case "blackbox":
+ // remove linked actions panel
+ mainJPanel.remove(linkedActionsJPanel);
+ mainJPanel.remove(linkedActionsJSeparator);
+ break;
+ default: // normal
+ // remove linked actions panel
+ mainJPanel.remove(linkedActionsJPanel);
+ mainJPanel.remove(linkedActionsJSeparator);
+
+ // remove docker image panel
+ mainJPanel.remove(dockerImageJPanel);
+ mainJPanel.remove(dockerImageJSeparator);
+
+ // remove code type panel
+ mainJPanel.remove(codeTypeJPanel);
+ mainJPanel.remove(codeTypeJSeparator);
+ }
+
+ runtimeJComboBox.setModel(new ComboBoxModel<Runtime>() {
+ private Runtime selected;
+
+ @Override
+ public void setSelectedItem(Object anItem) {
+ selected = (Runtime) anItem;
+ }
+
+ @Override
+ public Runtime getSelectedItem() {
+ return this.selected;
+ }
+
+ @Override
+ public int getSize() {
+ return Runtime.values().length;
+ }
+
+ @Override
+ public Runtime getElementAt(int index) {
+ return Runtime.toRuntime(index);
+ }
+
+ @Override
+ public void addListDataListener(ListDataListener l) {
+ // nothing to do
+ }
+
+ @Override
+ public void removeListDataListener(ListDataListener l) {
+ // nothing to do
+ }
+ });
+
+ if (!webactionJCheckBox.isSelected()) {
+ // raw http
+ rawHttpJCheckBox.setEnabled(false);
+ // custom option header
+ customOptionHeaderJCheckBox.setEnabled(false);
+ // final option
+ finalOptionJCheckBox.setEnabled(false);
+ }
+
+ webactionJCheckBox.addChangeListener(e -> {
+ AbstractButton abstractButton = (AbstractButton) e.getSource();
+ ButtonModel buttonModel = abstractButton.getModel();
+
+ if (buttonModel.isSelected()) {
+ // raw http
+ rawHttpJCheckBox.setEnabled(true);
+ // custom option header
+ customOptionHeaderJCheckBox.setEnabled(true);
+ // final option
+ finalOptionJCheckBox.setEnabled(true);
+ } else {
+ // raw http
+ rawHttpJCheckBox.setSelected(false);
+ rawHttpJCheckBox.setEnabled(false);
+ // custom option header
+ customOptionHeaderJCheckBox.setSelected(false);
+ customOptionHeaderJCheckBox.setEnabled(false);
+ // final option
+ finalOptionJCheckBox.setSelected(false);
+ finalOptionJCheckBox.setEnabled(false);
+ }
+ });
+
+ /**
+ * Set Value
+ */
+ // runtime
+ runtimeJComboBox.setSelectedItem(Runtime.toRuntime(action.getKind()));
+ // timeout
+ timeoutJSpinner.setValue(action.getLimits().getTimeout());
+ // memory
+ memoryJSpinner.setValue(action.getLimits().getMemory());
+ // webaction
+ webactionJCheckBox.setSelected(action.isWebAction());
+ // raw http
+ rawHttpJCheckBox.setSelected(action.isRawHttp());
+ // custom option header
+ customOptionHeaderJCheckBox.setSelected(action.isCustomOptions());
+ // final option
+ finalOptionJCheckBox.setSelected(action.isFinalDefaultParameter());
+
+ try {
+ // default parameter
+ defaultParameterForm.setDefaultParameter(JsonParserUtils.writeParameterToJson(action.getParameters()));
+ } catch (IOException e) {
+ LOG.error("Failed to parse json: " + action.getFullyQualifiedName(), e);
+ }
+ // docker image url
+ dockerImageForm.setDockerImage(action.getExec().getImage());
+ // code type
+ action.getCodeType().ifPresent(codeType -> codeTypeForm.setCodeType(codeType));
+
+ /**
+ * Set runtime event
+ */
+ runtimeJComboBox.addItemListener(e -> {
+ if (e.getStateChange() != ItemEvent.SELECTED) {
+ return;
+ }
+
+ switch ((Runtime) e.getItem()) {
+ case SEQUENCE:
+ removeAllPanel();
+
+ mainJPanel.add(linkedActionsJPanel, new GridConstraints(7, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, 150), new Dimension(-1, -1), 0));
+ mainJPanel.add(linkedActionsJSeparator, new GridConstraints(8, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, 5), 0));
+
+ mainJPanel.updateUI();
+ break;
+ case DOCKER:
+ removeAllPanel();
+
+ mainJPanel.add(dockerImageJPanel, new GridConstraints(7, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, -1), 0));
+ mainJPanel.add(dockerImageJSeparator, new GridConstraints(8, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, 5), 0));
+
+ mainJPanel.add(codeTypeJPanel, new GridConstraints(9, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, -1), 0));
+ mainJPanel.add(codeTypeJSeparator, new GridConstraints(10, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, 5), 0));
+
+ mainJPanel.add(defaultParameterJPanel, new GridConstraints(11, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, -1), 0));
+ mainJPanel.add(defaultParameterJSeparator, new GridConstraints(12, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, 5), 0));
+
+ mainJPanel.updateUI();
+ break;
+ default: // normal
+ removeAllPanel();
+
+ mainJPanel.add(defaultParameterJPanel, new GridConstraints(7, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, -1), 0));
+ mainJPanel.add(defaultParameterJSeparator, new GridConstraints(8, 0, 1, 1,
+ SIZEPOLICY_FIXED, SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(-1, -1), new Dimension(-1, 5), 0));
+
+ mainJPanel.updateUI();
+ }
+ });
+ }
+
+ private void removeAllPanel() {
+ // remove linked actions panel
+ mainJPanel.remove(linkedActionsJPanel);
+ mainJPanel.remove(linkedActionsJSeparator);
+
+ // remove docker image panel
+ mainJPanel.remove(dockerImageJPanel);
+ mainJPanel.remove(dockerImageJSeparator);
+
+ // remove code type panel
+ mainJPanel.remove(codeTypeJPanel);
+ mainJPanel.remove(codeTypeJSeparator);
+
+ // remove default parameter panel
+ mainJPanel.remove(defaultParameterJPanel);
+ mainJPanel.remove(defaultParameterJSeparator);
+ }
+
+ public void updateAction() {
+ try {
+ // parameters
+ Optional<String> params = getParameter();
+ if (!params.isPresent()) {
+ NOTIFIER.notify(project, "The json format of the parameter is incorrect.", NotificationType.ERROR);
+ return;
+ }
+ List<Map<String, Object>> validParams = ParameterUtils.mapToListMap(JsonParserUtils.parseMap(params.get()));
+ // timeout
+ int timeout = (Integer) timeoutJSpinner.getValue();
+ // memory
+ int memory = (Integer) memoryJSpinner.getValue();
+ Limits limits = action.getLimits();
+ limits.setTimeout(timeout);
+ limits.setMemory(memory);
+ // runtime
+ Runtime runtime = (Runtime) runtimeJComboBox.getSelectedItem();
+ CodeExec exec = createExec(action, runtime);
+ // web action
+ boolean web = webactionJCheckBox.isSelected();
+ boolean rawHttp = rawHttpJCheckBox.isSelected();
+ boolean customOption = customOptionHeaderJCheckBox.isSelected();
+ boolean finalDefaultParameter = finalOptionJCheckBox.isSelected();
+ // code type
+ Optional<String> codeType = getCodeType(runtime);
+ // annotations
+ List<Map<String, Object>> annotations = annotationToCollection(action, web, rawHttp, customOption, finalDefaultParameter, codeType);
+
+ // payload
+ Map<String, Object> payload = new LinkedHashMap<>();
+ payload.put("namespace", action.getNamespacePath());
+ payload.put("name", action.getWhiskPackage().map(pkg -> pkg + "/" + action.getName()).orElse(action.getName()));
+ payload.put("parameters", validParams);
+ payload.put("annotations", annotations);
+ payload.put("limits", limits);
+ payload.put("exec", exec);
+ whiskActionService.updateWhiskAction(whiskAuth, action, payload).ifPresent(updated -> {
+ NOTIFIER.notify(project, "Action update succeeded: " + updated.getFullyQualifiedName(), NotificationType.INFORMATION);
+ EventUtils.publish(project, RefreshActionOrTriggerListener.TOPIC, RefreshActionOrTriggerListener::fetchActionMetadata);
+ EventUtils.publish(project, RefreshWhiskTreeListener.TOPIC, RefreshWhiskTreeListener::refreshWhiskTree);
+ });
+ } catch (IOException e) {
+ String msg = "Failed to update action: " + action.getFullyQualifiedName();
+ LOG.error(msg, e);
+ NOTIFIER.notify(project, msg, NotificationType.ERROR);
+ }
+ }
+
+ private Optional<String> getCodeType(Runtime runtime) {
+ switch (runtime) {
+ case DOCKER:
+ Runtime codeType = codeTypeForm.getSelectedCodeType();
+ return Optional.ofNullable(codeType.toString());
+ default:
+ return Optional.empty();
+ }
+ }
+
+ private Optional<String> getParameter() {
+ if (defaultParameterForm == null) {
+ return Optional.of("{}");
+ }
+ return ParameterUtils.validateParams(defaultParameterForm.getDefaultParameter());
+ }
+
+ private CodeExec createExec(ExecutableWhiskAction executableWhiskAction, Runtime runtime) {
+ CodeExec codeExec = executableWhiskAction.getExec();
+ codeExec.setKind(runtime.toString());
+
+ switch (runtime) {
+ case SEQUENCE:
+ codeExec.setComponents(linkedActionsForm.getComponents());
+ break;
+ case DOCKER:
+ codeExec.setImage(dockerImageForm.getDockerImage());
+ break;
+ default: // normal
+ }
+
+ return codeExec;
+ }
+
+ private List<Map<String, Object>> annotationToCollection(ExecutableWhiskAction executableWhiskAction,
+ boolean web,
+ boolean rawHttp,
+ boolean customOption,
+ boolean finalDefaultParameter,
+ Optional<String> codeType) {
+ Map<String, Object> annotations = ParameterUtils.listMapToMap(executableWhiskAction.getAnnotations());
+ annotations.put("web-export", web);
+ annotations.put("raw-http", rawHttp);
+ annotations.put("web-custom-options", customOption);
+ annotations.put("final", finalDefaultParameter);
+ codeType.map(ct -> annotations.put("code-type", ct));
+ return ParameterUtils.mapToListMap(annotations);
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/CodeTypeForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/CodeTypeForm.form
new file mode 100644
index 0000000..e4c6cab
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/CodeTypeForm.form
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.action.ui.CodeTypeForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="811" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="16beb" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Code Type"/>
+ </properties>
+ </component>
+ <component id="2ec8b" class="javax.swing.JComboBox" binding="codeTypeJComboBox">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="af638" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/CodeTypeForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/CodeTypeForm.java
new file mode 100644
index 0000000..3314167
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/CodeTypeForm.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.ui;
+
+import com.navercorp.openwhisk.intellij.common.whisk.model.Runtime;
+
+import javax.swing.*;
+import javax.swing.event.ListDataListener;
+
+public class CodeTypeForm {
+ private JPanel mainJPanel;
+ private JComboBox codeTypeJComboBox;
+
+ public CodeTypeForm() {
+
+ codeTypeJComboBox.setModel(new ComboBoxModel<Runtime>() {
+ private Runtime selected;
+
+ @Override
+ public void setSelectedItem(Object anItem) {
+ selected = (Runtime) anItem;
+ }
+
+ @Override
+ public Object getSelectedItem() {
+ return this.selected;
+ }
+
+ @Override
+ public int getSize() {
+ // remove blackbox, sequence
+ return Runtime.values().length - 2;
+ }
+
+ @Override
+ public Runtime getElementAt(int index) {
+ return Runtime.toCodeType(index);
+ }
+
+ @Override
+ public void addListDataListener(ListDataListener l) {
+ // nothing to do
+ }
+
+ @Override
+ public void removeListDataListener(ListDataListener l) {
+ // nothing to do
+ }
+ });
+ }
+
+ public void setCodeType(String codeType) {
+ Runtime runtime = Runtime.toRuntime(codeType);
+ switch (runtime) {
+ case SEQUENCE:
+ case DOCKER:
+ break;
+ default: // normal
+ codeTypeJComboBox.setSelectedItem(runtime);
+ }
+ }
+
+ public Runtime getSelectedCodeType() {
+ return (Runtime) codeTypeJComboBox.getSelectedItem();
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DefaultParameterForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DefaultParameterForm.form
new file mode 100644
index 0000000..4c08f09
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DefaultParameterForm.form
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.action.ui.DefaultParameterForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="dc471" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Default Parameter"/>
+ </properties>
+ </component>
+ <scrollpane id="c704a">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="150"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="e3336" class="javax.swing.JTextArea" binding="defaultParameterJTextArea">
+ <constraints/>
+ <properties/>
+ </component>
+ </children>
+ </scrollpane>
+ <component id="146a8" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DefaultParameterForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DefaultParameterForm.java
new file mode 100644
index 0000000..bcdac1e
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DefaultParameterForm.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.ui;
+
+import javax.swing.*;
+
+public class DefaultParameterForm {
+ private JPanel mainJPanel;
+ private JTextArea defaultParameterJTextArea;
+
+ public DefaultParameterForm() {
+
+ }
+
+ public void setDefaultParameter(String parameter) {
+ defaultParameterJTextArea.setText(parameter);
+ }
+
+ public String getDefaultParameter() {
+ return defaultParameterJTextArea.getText();
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DockerImageForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DockerImageForm.form
new file mode 100644
index 0000000..45720b1
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DockerImageForm.form
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.action.ui.DockerImageForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="724b3" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Image"/>
+ </properties>
+ </component>
+ <component id="8e07" class="javax.swing.JTextField" binding="dockerImageJTextField">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="c87" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DockerImageForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DockerImageForm.java
new file mode 100644
index 0000000..c07ecab
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/DockerImageForm.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.ui;
+
+import javax.swing.*;
+
+public class DockerImageForm {
+ private JTextField dockerImageJTextField;
+ private JPanel mainJPanel;
+
+ public DockerImageForm() {
+
+ }
+
+ public void setDockerImage(String dockerImage) {
+ dockerImageJTextField.setText(dockerImage);
+ }
+
+ public String getDockerImage() {
+ return dockerImageJTextField.getText();
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsEntryForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsEntryForm.form
new file mode 100644
index 0000000..3050ceb
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsEntryForm.form
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.action.ui.LinkedActionsEntryForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="1" column-count="5" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="ac3fe" class="javax.swing.JLabel" binding="indexJLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="50" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="5ae4" class="javax.swing.JTextField" binding="actionJTextField">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="360" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="89105" class="javax.swing.JButton" binding="upJButton">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="30" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="afc8f" class="javax.swing.JButton" binding="downJButton">
+ <constraints>
+ <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="30" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="fa2ee" class="javax.swing.JButton" binding="removeJButton">
+ <constraints>
+ <grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="30" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsEntryForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsEntryForm.java
new file mode 100644
index 0000000..9bb5739
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsEntryForm.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.ui;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.navercorp.openwhisk.intellij.explorer.dialog.action.listener.DownActionListener;
+import com.navercorp.openwhisk.intellij.explorer.dialog.action.listener.RemoveActionListener;
+import com.navercorp.openwhisk.intellij.explorer.dialog.action.listener.UpActionListener;
+
+import javax.swing.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import static com.intellij.icons.AllIcons.General.Remove;
+import static com.navercorp.openwhisk.intellij.common.Icons.ARROW_DOWN;
+import static com.navercorp.openwhisk.intellij.common.Icons.ARROW_UP;
+
+public class LinkedActionsEntryForm {
+ private static final Logger LOG = Logger.getInstance(LinkedActionsEntryForm.class);
+
+ private JPanel mainJPanel;
+ private JTextField actionJTextField;
+ private JButton upJButton;
+ private JButton downJButton;
+ private JButton removeJButton;
+ private JLabel indexJLabel;
+
+ private String namespace;
+
+ public LinkedActionsEntryForm(int index,
+ String namespace,
+ String actionName,
+ UpActionListener upActionListener,
+ DownActionListener downActionListener,
+ RemoveActionListener removeActionListener) {
+ this.namespace = namespace;
+
+ indexJLabel.setText(String.valueOf(index));
+ indexJLabel.setHorizontalAlignment(SwingConstants.CENTER);
+ setActionName(actionName);
+
+ upJButton.setIcon(ARROW_UP);
+ upJButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ upActionListener.upAction(Integer.parseInt(indexJLabel.getText()));
+ }
+ });
+
+ downJButton.setIcon(ARROW_DOWN);
+ downJButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ downActionListener.downAction(Integer.parseInt(indexJLabel.getText()));
+ }
+ });
+
+ removeJButton.setIcon(Remove);
+ removeJButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ removeActionListener.removeAction(Integer.parseInt(indexJLabel.getText()));
+ }
+ });
+ }
+
+ private void setActionName(String actionName) {
+ String name = actionName.replaceAll("/" + namespace + "/", "");
+ actionJTextField.setText(name);
+ }
+
+ public String getActionName() {
+ return "/" + namespace + "/" + actionJTextField.getText();
+ }
+
+ public void setIndex(int index) {
+ indexJLabel.setText(String.valueOf(index));
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsForm.form
new file mode 100644
index 0000000..078e2f7
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsForm.form
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.action.ui.LinkedActionsForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="960cb" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Linked Actions"/>
+ </properties>
+ </component>
+ <scrollpane id="70411">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="db8f" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints/>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="5365b" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="50" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Action"/>
+ </properties>
+ </component>
+ <component id="7c1b7" class="javax.swing.JComboBox" binding="actionsJComboBox">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="520" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="56534" class="javax.swing.JButton" binding="addJButton">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="30" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <grid id="83040" binding="linkedActionsJPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ </children>
+ </grid>
+ </children>
+ </scrollpane>
+ <component id="278f2" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsForm.java
new file mode 100644
index 0000000..4d6fc35
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/action/ui/LinkedActionsForm.java
@@ -0,0 +1,180 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.action.ui;
+
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.WhiskActionMetaData;
+import com.navercorp.openwhisk.intellij.common.notification.SimpleNotifier;
+
+import javax.swing.*;
+import javax.swing.event.ListDataListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.intellij.icons.AllIcons.General.Add;
+
+public class LinkedActionsForm {
+ private static final Logger LOG = Logger.getInstance(LinkedActionsForm.class);
+ private static final SimpleNotifier NOTIFIER = SimpleNotifier.getInstance();
+
+ private JPanel mainJPanel;
+ private JComboBox actionsJComboBox;
+ private JButton addJButton;
+ private JPanel linkedActionsJPanel;
+
+ private Project project;
+ private List<LinkedActionsEntryForm> cachedActions = new ArrayList<>();
+
+ public LinkedActionsForm(Project project, String namespace, List<WhiskActionMetaData> actions, List<String> components) {
+ this.project = project;
+
+ for (int i = 0; i < components.size(); i++) {
+ addLinkedAction(i, namespace, components.get(i));
+ }
+
+ actionsJComboBox.setModel(new ComboBoxModel() {
+ private WhiskActionMetaData selected;
+
+ @Override
+ public void setSelectedItem(Object anItem) {
+ selected = (WhiskActionMetaData) anItem;
+ }
+
+ @Override
+ public Object getSelectedItem() {
+ return selected;
+ }
+
+ @Override
+ public int getSize() {
+ return actions.size();
+ }
+
+ @Override
+ public Object getElementAt(int index) {
+ return actions.get(index);
+ }
+
+ @Override
+ public void addListDataListener(ListDataListener l) {
+ // nothing to do
+ }
+
+ @Override
+ public void removeListDataListener(ListDataListener l) {
+ // nothing to do
+ }
+ });
+
+ addJButton.setIcon(Add);
+ addJButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (actionsJComboBox.getSelectedItem() == null) {
+ return;
+ }
+
+ WhiskActionMetaData action = (WhiskActionMetaData) actionsJComboBox.getSelectedItem();
+ String actionName = action.getWhiskPackage().map(pkg -> pkg + "/" + action.getName()).orElse(action.getName());
+ addLinkedAction(cachedActions.size(), namespace, actionName);
+ }
+ });
+ }
+
+ public List<String> getComponents() {
+ return cachedActions.stream().map(LinkedActionsEntryForm::getActionName).collect(Collectors.toList());
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+
+ /**
+ * Helper functions.
+ */
+ private void addLinkedAction(int index, String namespace, String actionName) {
+ LinkedActionsEntryForm entry = new LinkedActionsEntryForm(index, namespace, actionName,
+ this::upLinkedAction,
+ this::downLinkedAction,
+ this::removeLinkedAction);
+ linkedActionsJPanel.setLayout(new BoxLayout(linkedActionsJPanel, BoxLayout.Y_AXIS));
+ linkedActionsJPanel.add(entry.getContent());
+ cachedActions.add(entry);
+ linkedActionsJPanel.updateUI();
+ }
+
+ private void upLinkedAction(int index) {
+ if (index <= 0) {
+ return;
+ }
+
+ for (int i = index - 1; i < cachedActions.size(); i++) {
+ linkedActionsJPanel.remove(cachedActions.get(i).getContent());
+ }
+
+ Collections.swap(cachedActions, index - 1, index);
+
+ for (int i = index - 1; i < cachedActions.size(); i++) {
+ LinkedActionsEntryForm l = cachedActions.get(i);
+ l.setIndex(i);
+ linkedActionsJPanel.add(l.getContent());
+ }
+
+ linkedActionsJPanel.updateUI();
+ }
+
+ private void downLinkedAction(int index) {
+ if (index >= cachedActions.size() - 1) {
+ return;
+ }
+
+ for (int i = index; i < cachedActions.size(); i++) {
+ linkedActionsJPanel.remove(cachedActions.get(i).getContent());
+ }
+
+ Collections.swap(cachedActions, index, index + 1);
+
+ for (int i = index; i < cachedActions.size(); i++) {
+ LinkedActionsEntryForm l = cachedActions.get(i);
+ l.setIndex(i);
+ linkedActionsJPanel.add(l.getContent());
+ }
+
+ linkedActionsJPanel.updateUI();
+ }
+
+ private void removeLinkedAction(int index) {
+ if (cachedActions.size() <= 1) {
+ NOTIFIER.notify(project, "Sequence actions require at least one action.", NotificationType.WARNING);
+ return;
+ }
+
+ linkedActionsJPanel.remove(cachedActions.get(index).getContent());
+ cachedActions.remove(index);
+ for (int i = index; i < cachedActions.size(); i++) {
+ cachedActions.get(i).setIndex(i);
+ }
+
+ linkedActionsJPanel.updateUI();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/AddEndpointDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/AddEndpointDialog.java
new file mode 100644
index 0000000..f3bbf3d
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/AddEndpointDialog.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.endpoint;
+
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.DialogWrapperWithApply;
+import com.navercorp.openwhisk.intellij.explorer.dialog.endpoint.ui.AddEndpointDialogForm;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class AddEndpointDialog extends DialogWrapperWithApply {
+
+ private AddEndpointDialogForm addEndpointDialogForm;
+
+ public AddEndpointDialog(Project project) {
+ super(project, true); // use current window as parent
+ addEndpointDialogForm = new AddEndpointDialogForm(project);
+ setTitle("Add Endpoint");
+ setResizable(false);
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ if (addEndpointDialogForm != null) {
+ return addEndpointDialogForm.getContent();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected void doApplyAction() {
+ if (addEndpointDialogForm != null) {
+ addEndpointDialogForm.addEndpoint();
+ }
+ super.doApplyAction();
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (addEndpointDialogForm != null && !myApplyAction.isApplied()) {
+ addEndpointDialogForm.addEndpoint();
+ }
+ super.doOKAction();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/DeleteEndpointDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/DeleteEndpointDialog.java
new file mode 100644
index 0000000..f0bd398
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/DeleteEndpointDialog.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.endpoint;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class DeleteEndpointDialog extends DialogWrapper {
+
+ private WhiskEndpoint whiskEndpoint;
+
+ public DeleteEndpointDialog(Project project, WhiskEndpoint whiskEndpoint) {
+ super(true); // use current window as parent
+ setTitle("Delete Endpoint");
+ setResizable(false);
+ this.whiskEndpoint = whiskEndpoint;
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ JPanel dialogPanel = new JPanel(new BorderLayout());
+
+ JLabel label = new JLabel("Are you sure you want to delete " + whiskEndpoint.getAlias() + " endpoint?");
+ label.setPreferredSize(new Dimension(100, 30));
+ dialogPanel.add(label, BorderLayout.CENTER);
+
+ return dialogPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/EditEndpointDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/EditEndpointDialog.java
new file mode 100644
index 0000000..78b8a87
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/EditEndpointDialog.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.endpoint;
+
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.DialogWrapperWithApply;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+import com.navercorp.openwhisk.intellij.explorer.dialog.endpoint.ui.EditEndpointDialogForm;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class EditEndpointDialog extends DialogWrapperWithApply {
+
+ private EditEndpointDialogForm editEndpointDialogForm;
+
+ public EditEndpointDialog(Project project, WhiskEndpoint whiskEndpoint) {
+ super(project, true); // use current window as parent
+ editEndpointDialogForm = new EditEndpointDialogForm(project, whiskEndpoint);
+ setTitle("Edit Endpoint");
+ setResizable(false);
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ if (editEndpointDialogForm != null) {
+ return this.editEndpointDialogForm.getContent();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected void doApplyAction() {
+ if (editEndpointDialogForm != null) {
+ editEndpointDialogForm.updateEndpoint();
+ }
+ super.doApplyAction();
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (editEndpointDialogForm != null && !myApplyAction.isApplied()) {
+ editEndpointDialogForm.updateEndpoint();
+ }
+ super.doOKAction();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/AddEndpointDialogForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/AddEndpointDialogForm.form
new file mode 100644
index 0000000..3392fc4
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/AddEndpointDialogForm.form
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.endpoint.ui.AddEndpointDialogForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="401ea" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="6e866" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Alias"/>
+ </properties>
+ </component>
+ <component id="330f9" class="javax.swing.JTextField" binding="aliasJTextField">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="366c6" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="11db1" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="34574" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Apihost"/>
+ </properties>
+ </component>
+ <component id="5bf65" class="javax.swing.JTextField" binding="apihostJTextField">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="f57a8" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="8df6d" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="7794b" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/AddEndpointDialogForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/AddEndpointDialogForm.java
new file mode 100644
index 0000000..669b5b2
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/AddEndpointDialogForm.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.endpoint.ui;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.service.WhiskService;
+import com.navercorp.openwhisk.intellij.common.utils.EventUtils;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+import com.navercorp.openwhisk.intellij.explorer.toolwindow.listener.RefreshWhiskTreeListener;
+import com.navercorp.openwhisk.intellij.common.notification.SimpleNotifier;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class AddEndpointDialogForm {
+ private static final Logger LOG = Logger.getInstance(AddEndpointDialogForm.class);
+ private static final SimpleNotifier NOTIFIER = SimpleNotifier.getInstance();
+
+ private JPanel mainJPanel;
+ private JTextField aliasJTextField;
+ private JTextField apihostJTextField;
+
+ private WhiskService whiskService;
+ private List<WhiskEndpoint> endpoints;
+
+ private Project project;
+
+ public AddEndpointDialogForm(Project project) {
+ this.project = project;
+
+ /**
+ * Load endpoints
+ */
+ this.whiskService = ServiceManager.getService(project, WhiskService.class);
+ try {
+ endpoints = new ArrayList<>(JsonParserUtils.parseWhiskEndpoints(whiskService.getEndpoints())); // make mutable
+ } catch (IOException e) {
+ LOG.error("Endpoint parsing failed", e);
+ }
+
+ }
+
+ public void addEndpoint() {
+ final String alias = aliasJTextField.getText().trim();
+ final String apihost = apihostJTextField.getText().trim(); // TODO validate api host
+
+ if (existAlias(endpoints, alias)) {
+ NOTIFIER.notify(project, "Failed to added endpoint: " + alias + " already exists.", NotificationType.ERROR);
+ } else {
+ endpoints.add(new WhiskEndpoint(alias, apihost, new ArrayList<>()));
+ saveEndpoints(endpoints);
+
+ // Update action tree
+ EventUtils.publish(project, RefreshWhiskTreeListener.TOPIC, RefreshWhiskTreeListener::refreshWhiskTree);
+ NOTIFIER.notify(project, alias + " has been added successfully.", NotificationType.INFORMATION);
+ }
+ }
+
+ private boolean existAlias(List<WhiskEndpoint> whiskEndpoints, String alias) {
+ for (WhiskEndpoint ep : whiskEndpoints) {
+ if (ep.getAlias().equals(alias)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void saveEndpoints(List<WhiskEndpoint> newEndpoints) {
+ try {
+ String eps = JsonParserUtils.writeEndpointsToJson(newEndpoints);
+ whiskService.setEndpoints(eps);
+ whiskService.loadState(whiskService);
+ } catch (JsonProcessingException e) {
+ LOG.error("Endpoint parsing failed", e);
+ }
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/EditEndpointDialogForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/EditEndpointDialogForm.form
new file mode 100644
index 0000000..82f636a
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/EditEndpointDialogForm.form
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.endpoint.ui.EditEndpointDialogForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="3b01a" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="4ed82" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Alias"/>
+ </properties>
+ </component>
+ <component id="e975e" class="javax.swing.JTextField" binding="aliasJTextField">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="3d5e6" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="a4647" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="dc17c" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Apihost"/>
+ </properties>
+ </component>
+ <component id="f76a8" class="javax.swing.JTextField" binding="apihostJTextField">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="eb8b4" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="320bb" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="78128" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/EditEndpointDialogForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/EditEndpointDialogForm.java
new file mode 100644
index 0000000..8714a4d
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/endpoint/ui/EditEndpointDialogForm.java
@@ -0,0 +1,115 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.endpoint.ui;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.service.WhiskService;
+import com.navercorp.openwhisk.intellij.common.utils.EventUtils;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import com.navercorp.openwhisk.intellij.explorer.toolwindow.listener.RefreshWhiskTreeListener;
+import com.navercorp.openwhisk.intellij.common.notification.SimpleNotifier;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class EditEndpointDialogForm {
+ private static final Logger LOG = Logger.getInstance(EditEndpointDialogForm.class);
+ private static final SimpleNotifier NOTIFIER = SimpleNotifier.getInstance();
+
+ private JPanel mainJPanel;
+ private JTextField aliasJTextField;
+ private JTextField apihostJTextField;
+
+ private WhiskService whiskService;
+ private List<WhiskEndpoint> endpoints;
+
+ private Project project;
+ private WhiskEndpoint whiskEndpoint;
+
+ public EditEndpointDialogForm(Project project, WhiskEndpoint whiskEndpoint) {
+ this.project = project;
+ this.whiskEndpoint = whiskEndpoint;
+
+ /**
+ * Load endpoints
+ */
+ this.whiskService = ServiceManager.getService(project, WhiskService.class);
+ try {
+ endpoints = new ArrayList<>(JsonParserUtils.parseWhiskEndpoints(whiskService.getEndpoints())); // make mutable
+ } catch (IOException e) {
+ LOG.error("Endpoint parsing failed", e);
+ }
+
+ aliasJTextField.setText(whiskEndpoint.getAlias());
+ apihostJTextField.setText(whiskEndpoint.getApihost());
+ }
+
+ public void updateEndpoint() {
+ final String alias = aliasJTextField.getText().trim();
+ final String apihost = apihostJTextField.getText().trim(); // TODO validate api host
+
+ if (existAlias(endpoints, whiskEndpoint.getAlias(), alias)) {
+ NOTIFIER.notify(project, "Failed to update endpoint: " + alias + " already exists.", NotificationType.ERROR);
+ } else {
+ List<WhiskEndpoint> newEndpoints = updateWhiskEndpoint(endpoints,
+ whiskEndpoint.getAlias(),
+ new WhiskEndpoint(alias, apihost, whiskEndpoint.getNamespaces()));
+ saveEndpoints(newEndpoints);
+
+ // Update action tree
+ EventUtils.publish(project, RefreshWhiskTreeListener.TOPIC, RefreshWhiskTreeListener::refreshWhiskTree);
+ NOTIFIER.notify(project, alias + " has been added successfully.", NotificationType.INFORMATION);
+ }
+ }
+
+ private List<WhiskEndpoint> updateWhiskEndpoint(List<WhiskEndpoint> eps, String key, WhiskEndpoint newEndpoint) {
+ for (int i = 0; i < eps.size(); i++) {
+ if (eps.get(i).getAlias().equals(key)) {
+ eps.set(i, newEndpoint);
+ }
+ }
+ return eps;
+ }
+
+ private boolean existAlias(List<WhiskEndpoint> whiskEndpoints, String originAlias, String alias) {
+ return whiskEndpoints.stream()
+ .filter(ep -> !ep.getAlias().equals(originAlias)) // exclude current endpoint
+ .anyMatch(ep -> ep.getAlias().equals(alias)); // find duplicated alias
+ }
+
+ private void saveEndpoints(List<WhiskEndpoint> newEndpoints) {
+ try {
+ String eps = JsonParserUtils.writeEndpointsToJson(newEndpoints);
+ whiskService.setEndpoints(eps);
+ whiskService.loadState(whiskService);
+ } catch (JsonProcessingException e) {
+ LOG.error("Endpoint parsing failed", e);
+ }
+ }
+
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/AddNamespaceDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/AddNamespaceDialog.java
new file mode 100644
index 0000000..bbab99f
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/AddNamespaceDialog.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.namespace;
+
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.DialogWrapperWithApply;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+import com.navercorp.openwhisk.intellij.explorer.dialog.namespace.ui.AddNamespaceDialogForm;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class AddNamespaceDialog extends DialogWrapperWithApply {
+
+ private AddNamespaceDialogForm addNamespaceDialogForm;
+
+ public AddNamespaceDialog(Project project, WhiskEndpoint whiskEndpoint) {
+ super(project, true); // use current window as parent
+ addNamespaceDialogForm = new AddNamespaceDialogForm(project, whiskEndpoint);
+ setTitle("Add Namespace");
+ setResizable(false);
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ if (addNamespaceDialogForm != null) {
+ return addNamespaceDialogForm.getContent();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected void doApplyAction() {
+ if (addNamespaceDialogForm != null) {
+ addNamespaceDialogForm.addNamespace();
+ }
+ super.doApplyAction();
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (addNamespaceDialogForm != null && !myApplyAction.isApplied()) {
+ addNamespaceDialogForm.addNamespace();
+ }
+ super.doOKAction();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/DeleteNamespaceDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/DeleteNamespaceDialog.java
new file mode 100644
index 0000000..b12b080
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/DeleteNamespaceDialog.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.namespace;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskNamespace;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class DeleteNamespaceDialog extends DialogWrapper {
+
+ private WhiskNamespace whiskNamespace;
+
+ public DeleteNamespaceDialog(Project project, WhiskNamespace whiskNamespace) {
+ super(true); // use current window as parent
+ setTitle("Delete Namespace");
+ setResizable(false);
+ this.whiskNamespace = whiskNamespace;
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ JPanel dialogPanel = new JPanel(new BorderLayout());
+
+ JLabel label = new JLabel("Are you sure you want to delete " + whiskNamespace.getPath() + " namespace?");
+ label.setPreferredSize(new Dimension(100, 30));
+ dialogPanel.add(label, BorderLayout.CENTER);
+
+ return dialogPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/EditNamespaceDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/EditNamespaceDialog.java
new file mode 100644
index 0000000..59a49e3
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/EditNamespaceDialog.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.namespace;
+
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.DialogWrapperWithApply;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskNamespace;
+import com.navercorp.openwhisk.intellij.explorer.dialog.namespace.ui.EditNamespaceDialogForm;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class EditNamespaceDialog extends DialogWrapperWithApply {
+
+ private EditNamespaceDialogForm editNamespaceDialogForm;
+
+ public EditNamespaceDialog(Project project, WhiskAuth whiskAuth, WhiskNamespace whiskNamespace) {
+ super(project, true); // use current window as parent
+ editNamespaceDialogForm = new EditNamespaceDialogForm(project, whiskAuth, whiskNamespace);
+ setTitle("Edit Namespace");
+ setResizable(false);
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ if (editNamespaceDialogForm != null) {
+ return this.editNamespaceDialogForm.getContent();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected void doApplyAction() {
+ if (editNamespaceDialogForm != null) {
+ editNamespaceDialogForm.updateNamespace();
+ }
+ super.doApplyAction();
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (editNamespaceDialogForm != null && !myApplyAction.isApplied()) {
+ editNamespaceDialogForm.updateNamespace();
+ }
+ super.doOKAction();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/AddNamespaceDialogForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/AddNamespaceDialogForm.form
new file mode 100644
index 0000000..d9cd4bd
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/AddNamespaceDialogForm.form
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.namespace.ui.AddNamespaceDialogForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="569" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="48a1a" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="3d4" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Auth Key"/>
+ </properties>
+ </component>
+ <component id="2385f" class="javax.swing.JPasswordField" binding="authKeyJPasswordField">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="1a120" class="javax.swing.JCheckBox" binding="showAuthKeyJCheckBox">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Show Key"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="4ab28" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="1094b" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="6c796" class="javax.swing.JButton" binding="verifyAuthKeyJButton">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ <maximum-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Verify AuthKey"/>
+ </properties>
+ </component>
+ <component id="1be9" class="javax.swing.JLabel" binding="verifyResultJLabel">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="d2d81" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ </children>
+ </grid>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/AddNamespaceDialogForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/AddNamespaceDialogForm.java
new file mode 100644
index 0000000..1f2cbc5
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/AddNamespaceDialogForm.java
@@ -0,0 +1,145 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.namespace.ui;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.JBColor;
+import com.navercorp.openwhisk.intellij.common.service.WhiskService;
+import com.navercorp.openwhisk.intellij.common.utils.EventUtils;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import com.navercorp.openwhisk.intellij.common.whisk.service.WhiskNamespaceService;
+import com.navercorp.openwhisk.intellij.explorer.toolwindow.listener.RefreshWhiskTreeListener;
+import com.navercorp.openwhisk.intellij.common.notification.SimpleNotifier;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskNamespace;
+
+import javax.swing.*;
+import java.awt.event.ItemEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class AddNamespaceDialogForm {
+ private static final Logger LOG = Logger.getInstance(AddNamespaceDialogForm.class);
+ private static final SimpleNotifier NOTIFIER = SimpleNotifier.getInstance();
+
+ private JPanel mainJPanel;
+ private JPasswordField authKeyJPasswordField;
+ private JButton verifyAuthKeyJButton;
+ private JLabel verifyResultJLabel;
+ private JCheckBox showAuthKeyJCheckBox;
+
+ private WhiskNamespaceService whiskNamespaceService = WhiskNamespaceService.getInstance();
+ private WhiskService whiskService;
+ private List<WhiskEndpoint> endpoints;
+
+ private Project project;
+ private WhiskEndpoint whiskEndpoint;
+
+ public AddNamespaceDialogForm(Project project, WhiskEndpoint whiskEndpoint) {
+ this.project = project;
+ this.whiskEndpoint = whiskEndpoint;
+
+ /**
+ * Load endpoints
+ */
+ this.whiskService = ServiceManager.getService(project, WhiskService.class);
+ try {
+ endpoints = new ArrayList<>(JsonParserUtils.parseWhiskEndpoints(whiskService.getEndpoints())); // make mutable
+ } catch (IOException e) {
+ LOG.error("Endpoint parsing failed", e);
+ }
+
+ verifyAuthKeyJButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ final String auth = new String(authKeyJPasswordField.getPassword());
+ final String apihost = whiskEndpoint.getApihost();
+ final WhiskAuth newWhiskAuth = new WhiskAuth(auth, apihost);
+ Optional<WhiskNamespace> result = whiskNamespaceService.validateNamespace(newWhiskAuth);
+ if (result.isPresent()) {
+ verifyResultJLabel.setText("Success");
+ verifyResultJLabel.setForeground(JBColor.GREEN);
+ } else {
+ verifyResultJLabel.setText("Invalid authkey");
+ verifyResultJLabel.setForeground(JBColor.RED);
+ }
+ }
+ });
+
+ showAuthKeyJCheckBox.addItemListener(e -> {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ authKeyJPasswordField.setEchoChar((char) 0);
+ } else {
+ authKeyJPasswordField.setEchoChar('*');
+ }
+ });
+ }
+
+ public void addNamespace() {
+ final String auth = new String(authKeyJPasswordField.getPassword());
+ final String apihost = whiskEndpoint.getApihost();
+ final WhiskAuth newWhiskAuth = new WhiskAuth(auth, apihost);
+ Optional<WhiskNamespace> result = whiskNamespaceService.validateNamespace(newWhiskAuth);
+ if (result.isPresent()) {
+ WhiskNamespace whiskNamespace = result.get();
+ List<WhiskEndpoint> newEndpoints = addNamespace(whiskEndpoint, whiskNamespace);
+ saveEndpoints(newEndpoints);
+
+ // Update action tree
+ EventUtils.publish(project, RefreshWhiskTreeListener.TOPIC, RefreshWhiskTreeListener::refreshWhiskTree);
+ NOTIFIER.notify(project, whiskNamespace.getPath() + " has been added successfully.", NotificationType.INFORMATION);
+ } else {
+ NOTIFIER.notify(project, "Invalid authkey", NotificationType.ERROR);
+ }
+ }
+
+ private List<WhiskEndpoint> addNamespace(WhiskEndpoint endpoint, WhiskNamespace whiskNamespace) {
+ for (int i = 0; i < endpoints.size(); i++) {
+ WhiskEndpoint ep = endpoints.get(i);
+ if (ep.getAlias().equals(endpoint.getAlias()) && ep.getApihost().equals(endpoint.getApihost())) {
+ List<WhiskNamespace> namespaces = ep.getNamespaces();
+ namespaces.add(whiskNamespace);
+ ep.setNamespaces(namespaces);
+ }
+ endpoints.set(i, ep);
+ }
+ return endpoints;
+ }
+
+ private void saveEndpoints(List<WhiskEndpoint> newEndpoints) {
+ try {
+ String eps = JsonParserUtils.writeEndpointsToJson(newEndpoints);
+ whiskService.setEndpoints(eps);
+ whiskService.loadState(whiskService);
+ } catch (JsonProcessingException e) {
+ LOG.error("Endpoint parsing failed", e);
+ }
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/EditNamespaceDialogForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/EditNamespaceDialogForm.form
new file mode 100644
index 0000000..94d394c
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/EditNamespaceDialogForm.form
@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.namespace.ui.EditNamespaceDialogForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="942" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="ac30b" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false">
+ <preferred-size width="500" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="ac8d2" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Name"/>
+ </properties>
+ </component>
+ <component id="4bc0d" class="javax.swing.JTextField" binding="nameJTextField">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <editable value="false"/>
+ </properties>
+ </component>
+ <component id="c2d6a" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="259ba" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false">
+ <preferred-size width="500" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="a750" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Auth Key"/>
+ </properties>
+ </component>
+ <component id="cc357" class="javax.swing.JPasswordField" binding="authKeyJPasswordField">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <echoChar value="*"/>
+ </properties>
+ </component>
+ <component id="ee04d" class="javax.swing.JCheckBox" binding="showAuthKeyJCheckbox">
+ <constraints>
+ <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Show Key"/>
+ </properties>
+ </component>
+ <component id="8c925" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="44877" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="true" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="4" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="500" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="db084" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="ae99f" class="javax.swing.JButton" binding="verifyAuthKeyJButton">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ <maximum-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Verify AuthKey"/>
+ </properties>
+ </component>
+ <component id="a7218" class="javax.swing.JLabel" binding="verifyResultJLabel">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <horizontalAlignment value="10"/>
+ <text value=""/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="8e824" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ </children>
+ </grid>
+ <component id="6a07a" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="ce2ed" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <hspacer id="2c3b2">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/EditNamespaceDialogForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/EditNamespaceDialogForm.java
new file mode 100644
index 0000000..9a363c4
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/namespace/ui/EditNamespaceDialogForm.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.namespace.ui;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.JBColor;
+import com.navercorp.openwhisk.intellij.common.service.WhiskService;
+import com.navercorp.openwhisk.intellij.common.utils.EventUtils;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import com.navercorp.openwhisk.intellij.common.whisk.service.WhiskNamespaceService;
+import com.navercorp.openwhisk.intellij.common.notification.SimpleNotifier;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskEndpoint;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskNamespace;
+import com.navercorp.openwhisk.intellij.explorer.toolwindow.listener.RefreshWhiskTreeListener;
+
+import javax.swing.*;
+import java.awt.event.ItemEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class EditNamespaceDialogForm {
+ private static final Logger LOG = Logger.getInstance(EditNamespaceDialogForm.class);
+ private static final SimpleNotifier NOTIFIER = SimpleNotifier.getInstance();
+
+ private JPanel mainJPanel;
+
+ private JTextField nameJTextField;
+ private JPasswordField authKeyJPasswordField;
+
+ private JButton verifyAuthKeyJButton;
+ private JLabel verifyResultJLabel;
+ private JCheckBox showAuthKeyJCheckbox;
+
+ private WhiskNamespaceService whiskNamespaceService = WhiskNamespaceService.getInstance();
+ private WhiskService whiskService;
+ private List<WhiskEndpoint> endpoints;
+
+ private Project project;
+ private WhiskAuth whiskAuth;
+ private WhiskNamespace whiskNamespace;
+
+ public EditNamespaceDialogForm(Project project, WhiskAuth whiskAuth, WhiskNamespace whiskNamespace) {
+ this.project = project;
+ this.whiskAuth = whiskAuth;
+ this.whiskNamespace = whiskNamespace;
+
+ /**
+ * Load endpoints
+ */
+ this.whiskService = ServiceManager.getService(project, WhiskService.class);
+ try {
+ endpoints = new ArrayList<>(JsonParserUtils.parseWhiskEndpoints(whiskService.getEndpoints())); // make mutable
+ } catch (IOException e) {
+ LOG.error("Endpoint parsing failed", e);
+ }
+
+ nameJTextField.setText(whiskNamespace.getPath());
+ authKeyJPasswordField.setText(whiskNamespace.getAuth());
+
+ verifyAuthKeyJButton.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ final String auth = new String(authKeyJPasswordField.getPassword());
+ final String apihost = whiskAuth.getApihost();
+ final WhiskAuth newWhiskAuth = new WhiskAuth(auth, apihost);
+ Optional<WhiskNamespace> result = whiskNamespaceService.validateNamespace(newWhiskAuth);
+ if (result.isPresent()) {
+ verifyResultJLabel.setText("Success");
+ verifyResultJLabel.setForeground(JBColor.GREEN);
+ } else {
+ verifyResultJLabel.setText("Invalid authkey");
+ verifyResultJLabel.setForeground(JBColor.RED);
+ }
+ }
+ });
+
+ showAuthKeyJCheckbox.addItemListener(e -> {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ authKeyJPasswordField.setEchoChar((char) 0);
+ } else {
+ authKeyJPasswordField.setEchoChar('*');
+ }
+ });
+ }
+
+ public void updateNamespace() {
+ final String auth = new String(authKeyJPasswordField.getPassword());
+ final String apihost = whiskAuth.getApihost();
+ final WhiskAuth newWhiskAuth = new WhiskAuth(auth, apihost);
+ Optional<WhiskNamespace> result = whiskNamespaceService.validateNamespace(newWhiskAuth);
+ if (result.isPresent()) {
+ WhiskNamespace newNamespace = result.get();
+ List<WhiskEndpoint> newEndpoints = updateNamespace(whiskNamespace, newNamespace);
+ saveEndpoints(newEndpoints);
+ nameJTextField.setText(newNamespace.getPath());
+
+ // Update action tree
+ EventUtils.publish(project, RefreshWhiskTreeListener.TOPIC, RefreshWhiskTreeListener::refreshWhiskTree);
+ NOTIFIER.notify(project, whiskNamespace.getPath() + " modification was successful.", NotificationType.INFORMATION);
+ } else {
+ NOTIFIER.notify(project, "Invalid authkey", NotificationType.ERROR);
+ }
+ }
+
+ private List<WhiskEndpoint> updateNamespace(WhiskNamespace originNamespace, WhiskNamespace newNamespace) {
+ for (int i = 0; i < endpoints.size(); i++) {
+ WhiskEndpoint endpoint = endpoints.get(i);
+ List<WhiskNamespace> namespaces = endpoint.getNamespaces();
+ for (int j = 0; j < namespaces.size(); j++) {
+ if (namespaces.get(j).getPath().equals(originNamespace.getPath())) {
+ namespaces.set(j, newNamespace);
+ }
+ }
+ endpoint.setNamespaces(namespaces);
+ endpoints.set(i, endpoint);
+ }
+ return endpoints;
+ }
+
+ private void saveEndpoints(List<WhiskEndpoint> newEndpoints) {
+ try {
+ String eps = JsonParserUtils.writeEndpointsToJson(newEndpoints);
+ whiskService.setEndpoints(eps);
+ whiskService.loadState(whiskService);
+ } catch (JsonProcessingException e) {
+ LOG.error("Endpoint parsing failed", e);
+ }
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/DeletePackageDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/DeletePackageDialog.java
new file mode 100644
index 0000000..e2784ed
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/DeletePackageDialog.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.pkg;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.navercorp.openwhisk.intellij.common.whisk.model.action.CompactWhiskAction;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackageWithActions;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class DeletePackageDialog extends DialogWrapper {
+
+ private WhiskPackageWithActions whiskPackage;
+
+ public DeletePackageDialog(Project project, WhiskPackageWithActions whiskPackage) {
+ super(true); // use current window as parent
+ setTitle("Delete Package");
+ setResizable(false);
+ this.whiskPackage = whiskPackage;
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ JPanel dialogPanel = new JPanel(new BorderLayout());
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("<html>");
+ builder.append("Are you sure you want to delete " + whiskPackage.getName() + " package?");
+ if (!whiskPackage.getBinding().isPresent()) {
+ if (!whiskPackage.getActions().isEmpty()) {
+ builder.append("<br/><br/>");
+ builder.append("The following actions will be deleted together<br/>");
+ }
+ for (CompactWhiskAction action : whiskPackage.getActions()) {
+ builder.append("- " + action.getName() + "<br/>");
+ }
+ builder.append("<br/><br/>");
+ }
+ builder.append("</html>");
+
+ JLabel label = new JLabel(builder.toString());
+ label.setPreferredSize(new Dimension(400, 100));
+ dialogPanel.add(label, BorderLayout.CENTER);
+
+ return dialogPanel;
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/PackageCreationManagerDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/PackageCreationManagerDialog.java
new file mode 100644
index 0000000..5de1397
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/PackageCreationManagerDialog.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.pkg;
+
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.DialogWrapperWithApply;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.explorer.dialog.pkg.ui.PackageCreationManagerDialogForm;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class PackageCreationManagerDialog extends DialogWrapperWithApply {
+
+ private PackageCreationManagerDialogForm packageCreationManagerDialogForm;
+
+ public PackageCreationManagerDialog(Project project, WhiskAuth auth) {
+ super(project, true); // use current window as parent
+ packageCreationManagerDialogForm = new PackageCreationManagerDialogForm(project, auth);
+ setTitle("Create Package");
+ setResizable(false);
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ if (packageCreationManagerDialogForm != null) {
+ return packageCreationManagerDialogForm.getContent();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected void doApplyAction() {
+ if (packageCreationManagerDialogForm != null) {
+ packageCreationManagerDialogForm.createPackage();
+ }
+ super.doApplyAction();
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (packageCreationManagerDialogForm != null && !myApplyAction.isApplied()) {
+ packageCreationManagerDialogForm.createPackage();
+ }
+ super.doOKAction();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/PackageManagerDialog.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/PackageManagerDialog.java
new file mode 100644
index 0000000..78a366a
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/PackageManagerDialog.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.pkg;
+
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.DialogWrapperWithApply;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackageWithActions;
+import com.navercorp.openwhisk.intellij.explorer.dialog.pkg.ui.PackageManagerDialogForm;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class PackageManagerDialog extends DialogWrapperWithApply {
+
+ private PackageManagerDialogForm packageManagerDialogForm;
+
+ public PackageManagerDialog(Project project, WhiskAuth auth, WhiskPackageWithActions whiskPackage) {
+ super(project, true); // use current window as parent
+ packageManagerDialogForm = new PackageManagerDialogForm(project, auth, whiskPackage);
+ setTitle("Manage Package");
+ setResizable(false);
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ if (packageManagerDialogForm != null) {
+ return this.packageManagerDialogForm.getContent();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected void doApplyAction() {
+ if (packageManagerDialogForm != null) {
+ packageManagerDialogForm.updatePackage();
+ }
+ super.doApplyAction();
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (packageManagerDialogForm != null && !myApplyAction.isApplied()) {
+ packageManagerDialogForm.updatePackage();
+ }
+ super.doOKAction();
+ }
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageCreationManagerDialogForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageCreationManagerDialogForm.form
new file mode 100644
index 0000000..6e8a746
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageCreationManagerDialogForm.form
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.pkg.ui.PackageCreationManagerDialogForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="2d156" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="e6557" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="100" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Name"/>
+ </properties>
+ </component>
+ <component id="f6602" class="javax.swing.JTextField" binding="nameJTextField">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="62535" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="2f681" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="-1" height="5"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageCreationManagerDialogForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageCreationManagerDialogForm.java
new file mode 100644
index 0000000..9a10c24
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageCreationManagerDialogForm.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.pkg.ui;
+
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackageWithActions;
+import com.navercorp.openwhisk.intellij.common.whisk.service.WhiskPackageService;
+import com.navercorp.openwhisk.intellij.common.notification.SimpleNotifier;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class PackageCreationManagerDialogForm {
+ private static final Logger LOG = Logger.getInstance(PackageCreationManagerDialogForm.class);
+ private static final SimpleNotifier NOTIFIER = SimpleNotifier.getInstance();
+
+ private JTextField nameJTextField;
+ private JPanel mainJPanel;
+
+ private WhiskPackageService whiskPackageService = WhiskPackageService.getInstance();
+
+ private Project project;
+ private WhiskAuth whiskAuth;
+
+ public PackageCreationManagerDialogForm(Project project, WhiskAuth whiskAuth) {
+ this.project = project;
+ this.whiskAuth = whiskAuth;
+ }
+
+ public void createPackage() {
+ try {
+ String name = nameJTextField.getText().trim();
+
+ Map<String, Object> payload = new LinkedHashMap<>();
+ payload.put("name", name);
+ payload.put("namespace", "_");
+
+ Optional<WhiskPackageWithActions> created = whiskPackageService.createWhiskPackage(whiskAuth, name, payload);
+ if (created.isPresent()) {
+ NOTIFIER.notify(project, name + " created", NotificationType.INFORMATION);
+ } else {
+ NOTIFIER.notify(project, name + " already exist", NotificationType.ERROR);
+ }
+ } catch (IOException e) {
+ String msg = "Failed to create package: ";
+ LOG.error(msg, e);
+ NOTIFIER.notify(project, msg, NotificationType.ERROR);
+ }
+ }
+
+ public JPanel getContent() {
+ return mainJPanel;
+ }
+
+}
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageManagerDialogForm.form b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageManagerDialogForm.form
new file mode 100644
index 0000000..b7729e8
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageManagerDialogForm.form
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.navercorp.openwhisk.intellij.explorer.dialog.pkg.ui.PackageManagerDialogForm">
+ <grid id="27dc6" binding="mainJPanel" layout-manager="GridLayoutManager" row-count="6" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="1060" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="e083a" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="800" height="30"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="67410" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="635bb" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ <maximum-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Name"/>
+ </properties>
+ </component>
+ <component id="a98f5" class="javax.swing.JLabel" binding="nameJLabel">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="faa4" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="e942a" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="818fc" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ <maximum-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Namespace"/>
+ </properties>
+ </component>
+ <component id="4c848" class="javax.swing.JLabel" binding="namespaceJPanel">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="e60d9" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="73d3d" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="8ee3" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="800" height="30"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="d02f0" binding="sharedJPanel" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="58b28" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ <maximum-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Shared"/>
+ </properties>
+ </component>
+ <component id="c5ea3" class="javax.swing.JCheckBox" binding="shareJCheckBox">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="c38a4" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="d76d" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="a3d13" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ <maximum-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Version"/>
+ </properties>
+ </component>
+ <component id="c1dcf" class="javax.swing.JLabel" binding="versionJLabel">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="662c8" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="dd7ea" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="71261" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="800" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="d4c6f" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="-1"/>
+ <maximum-size width="150" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <text value="Default Parameter"/>
+ </properties>
+ </component>
+ <component id="f162d" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <maximum-size width="5" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <orientation value="1"/>
+ </properties>
+ </component>
+ <scrollpane id="20925">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="700" height="150"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="36ec3" class="javax.swing.JTextArea" binding="defaultParameterTextArea">
+ <constraints/>
+ <properties/>
+ </component>
+ </children>
+ </scrollpane>
+ </children>
+ </grid>
+ <component id="d0bd5" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="e5d4b" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="811bd" class="javax.swing.JSeparator">
+ <constraints>
+ <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageManagerDialogForm.java b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageManagerDialogForm.java
new file mode 100644
index 0000000..51937c3
--- /dev/null
+++ b/src/main/java/com/navercorp/openwhisk/intellij/explorer/dialog/pkg/ui/PackageManagerDialogForm.java
@@ -0,0 +1,131 @@
+/**
+ * Copyright 2020-present NAVER Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.navercorp.openwhisk.intellij.explorer.dialog.pkg.ui;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.intellij.notification.NotificationType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.uiDesigner.core.GridConstraints;
+import com.navercorp.openwhisk.intellij.common.notification.SimpleNotifier;
+import com.navercorp.openwhisk.intellij.common.utils.JsonParserUtils;
+import com.navercorp.openwhisk.intellij.common.utils.ParameterUtils;
+import com.navercorp.openwhisk.intellij.common.whisk.model.Binding;
+import com.navercorp.openwhisk.intellij.common.whisk.model.WhiskAuth;
+import com.navercorp.openwhisk.intellij.common.whisk.model.pkg.WhiskPackageWithActions;
+import com.navercorp.openwhisk.intellij.common.whisk.service.WhiskPackageService;
+import org.apache.commons.lang.StringUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static com.intellij.uiDesigner.core.GridConstraints.*;
+
+public class PackageManagerDialogForm {
+ private static final Logger LOG = Logger.getInstance(PackageManagerDialogForm.class);
+ private static final SimpleNotifier NOTIFIER = SimpleNotifier.getInstance();
+
+ private JPanel mainJPanel;
+ private JCheckBox shareJCheckBox;
+ private JLabel nameJLabel;
+ private JLabel namespaceJPanel;
+ private JLabel versionJLabel;
+ private JTextArea defaultParameterTextArea;
+ private JPanel sharedJPanel;
+
+ private WhiskPackageService whiskPackageService = WhiskPackageService.getInstance();
+
+ private Project project;
+ private WhiskAuth whiskAuth;
+ private WhiskPackageWithActions whiskPackage;
+
+ public PackageManagerDialogForm(Project project, WhiskAuth whiskAuth, WhiskPackageWithActions whiskPackage) {
+ this.project = project;
+ this.whiskAuth = whiskAuth;
+ this.whiskPackage = whiskPackage;
+
+ nameJLabel.setText(whiskPackage.getName());
+ namespaceJPanel.setText(whiskPackage.getNamespace());
+ versionJLabel.setText(whiskPackage.getVersion());
+
+ Optional<Binding> binding = whiskPackage.getBinding();
+ if (binding.isPresent()) {
+ sharedJPanel.remove(shareJCheckBox);
+ Binding b = binding.get();
+ JLabel label = new JLabel("from " + b.getNamespace() + "/" + b.getName());
+ label.setPreferredSize(new Dimension(250, -1));
+ sharedJPanel.add(label, new GridConstraints(0, 2, 1, 1,
+ SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK,
+ SIZEPOLICY_CAN_GROW | SIZEPOLICY_CAN_SHRINK, FILL_NONE, ANCHOR_CENTER,
+ new Dimension(-1, -1), new Dimension(250, -1), new Dimension(-1, -1), 0));
+ } else {
+ shareJCheckBox.setSelected(whiskPackage.isPublish());
+ }
+
+ try {
+ defaultParameterTextArea.setText(JsonParserUtils.writeParameterToJson(whiskPackage.getParameters()));
+ } catch (JsonProcessingException e) {
+ LOG.error("Failed to parse json: " + whiskPackage.getName(), e);
+ }
+ }
+
+ public void updatePackage() {
+ try {
+ /**
+ * Update default parameters
+ */
+ // parameters
+ List<Map<String, Object>> params = parametersToCollection(whiskPackage, defaultParameterTextArea.getText());
+ // payload
+ Map<String, Object> payload = new LinkedHashMap<>();
+ payload.put("name", whiskPackage.getName());
+ payload.put("namespace", whiskPackage.getNamespace());
+ payload.put("parameters", params);
+ if (shareJCheckBox.isValid()) {
+ payload.put("publish", shareJCheckBox.isSelected());
+ }
+
+ whiskPackageService.updateWhiskPackage(whiskAuth, whiskPackage.getName(), payload)
+ .ifPresent(updated -> NOTIFIER.notify(project, updated.getName() + " updated", NotificationType.INFORMATION));
+ } catch (IOException e) {
+ String msg = "Failed to update package: " + whiskPackage.getName();
+ LOG.error(msg, e);
+ NOTIFIER.notify(project, msg, NotificationType.ERROR);
+ }
+
+ }
+
+ private boolean validateParams(String params) throws IOException {
+ return JsonParserUtils.isValidJson(params);
+ }
+
+ private List<Map<String, Object>> parametersToCollection(WhiskPackageWithActions pkg, String param) throws IOException {
+ if (StringUtils.isEmpty(param) || !validateParams(param)) {
+ return pkg.getParameters();
+ }
+ return ParameterUtils.mapToListMap(JsonParserUtils.parseMap(param));
+ }
+
+ public JPanel getContent() {
... 9478 lines suppressed ...