29994d0932b622c6ae8988fca6fec3f8f4827d4c
[cli.git] / framework / src / main / java / org / onap / cli / fw / cmd / OnapCommand.java
1 /*
2  * Copyright 2017 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.cli.fw.cmd;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25 import org.onap.cli.fw.conf.OnapCommandConstants;
26 import org.onap.cli.fw.error.OnapCommandException;
27 import org.onap.cli.fw.error.OnapCommandHelpFailed;
28 import org.onap.cli.fw.error.OnapCommandNotInitialized;
29 import org.onap.cli.fw.info.OnapCommandInfo;
30 import org.onap.cli.fw.input.OnapCommandParameter;
31 import org.onap.cli.fw.input.OnapCommandParameterType;
32 import org.onap.cli.fw.output.OnapCommandResult;
33 import org.onap.cli.fw.output.OnapCommandResultAttribute;
34 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
35 import org.onap.cli.fw.output.OnapCommandResultType;
36 import org.onap.cli.fw.schema.OnapCommandSchemaInfo;
37 import org.onap.cli.fw.schema.OnapCommandSchemaLoader;
38 import org.onap.cli.fw.schema.OnapCommandSchemaMerger;
39 import org.onap.cli.fw.store.OnapCommandArtifactStore;
40 import org.onap.cli.fw.store.OnapCommandArtifactStore.Artifact;
41 import org.onap.cli.fw.store.OnapCommandExecutionStore.ExecutionStoreContext;
42 import org.onap.cli.fw.utils.OnapCommandHelperUtils;
43 import org.onap.cli.fw.utils.OnapCommandUtils;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 import com.google.gson.Gson;
48 import com.google.gson.GsonBuilder;
49
50
51 /**
52  * Oclip Command.
53  *
54  */
55 public abstract class OnapCommand {
56
57     private static Logger log = LoggerFactory.getLogger(OnapCommand.class);
58     private static Gson gson = new GsonBuilder().serializeNulls().create();
59
60     private String cmdDescription;
61
62     private String cmdName;
63
64     private String cmdSchemaName;
65
66     private OnapCommandInfo info = new OnapCommandInfo();
67
68     private Set<OnapCommandParameter> cmdParameters = new HashSet<>();
69
70     private OnapCommandResult cmdResult = new OnapCommandResult();
71
72     private List<String> defaultSchemas = new ArrayList<>();
73
74     protected boolean isInitialzied = false;
75
76     private  boolean isRpc = false;
77
78     private ExecutionStoreContext executionStoreContext;
79
80     public boolean isRpc() {
81         return isRpc;
82     }
83
84     public void setRpc(boolean isRpc) {
85         this.isRpc = isRpc;
86     }
87
88     protected OnapCommand() {
89         this.addDefaultSchemas(OnapCommandConstants.DEFAULT_PARAMETER_FILE_NAME);
90     }
91
92     public List<String> getSchemas() {
93         List<String> schemas = new ArrayList<>();
94         schemas.addAll(this.defaultSchemas);
95         schemas.add(this.getSchemaName());
96         return schemas;
97     }
98
99     public String getSchemaVersion() {
100         return OnapCommandConstants.OPEN_CLI_SCHEMA_VERSION_VALUE_1_0;
101     }
102
103     public String getDescription() {
104         return this.cmdDescription;
105     }
106
107     public void setDescription(String description) {
108         this.cmdDescription = description;
109     }
110
111     public String getName() {
112         return this.cmdName;
113     }
114
115     public void setName(String name) {
116         this.cmdName = name;
117     }
118
119     public OnapCommandInfo getInfo() {
120         return info;
121     }
122
123     public void setInfo(OnapCommandInfo info) {
124         this.info = info;
125     }
126
127     public void setParameters(Set<OnapCommandParameter> parameters) {
128         this.cmdParameters = parameters;
129     }
130
131     public Set<OnapCommandParameter> getParameters() {
132         return this.cmdParameters;
133     }
134
135     public Map<String, OnapCommandParameter> getParametersMap() {
136         return OnapCommandUtils.getInputMap(this.getParameters());
137     }
138
139     public OnapCommandResult getResult() {
140         return this.cmdResult;
141     }
142
143     public void setResult(OnapCommandResult result) {
144         this.cmdResult = result;
145     }
146
147     public String getSchemaName() {
148         return cmdSchemaName;
149     }
150
151     protected void setSchemaName(String schemaName) {
152         this.cmdSchemaName = schemaName;
153     }
154
155     protected void addDefaultSchemas(String schema) {
156         this.defaultSchemas.add(schema);
157     }
158
159     public List<String> getDefaultSchema() {
160         return this.defaultSchemas;
161     }
162
163     public List<String> getArgs() {
164         List <String> args = new ArrayList<>();
165         for (OnapCommandParameter param: this.getParameters()) {
166             args.add(OnapCommandParameter.printLongOption(param.getName()));
167             args.add(param.getValue().toString());
168         }
169
170         return args;
171     }
172
173     public String getArgsJson(boolean ignoreDefaults) {
174         Map <String, String> args = new HashMap<>();
175
176         for (OnapCommandParameter param: this.getParameters()) {
177             if (ignoreDefaults && param.isDefaultParam())
178                 continue;
179
180             args.put(param.getName(), param.getValue().toString());
181         }
182
183         try {
184             return gson.toJson(args);
185         } catch (Exception e) { // NOSONAR
186             log.error("exception occured {}", e.getMessage());
187             return "{}";
188         }
189     }
190
191     /**
192      * Initialize this command from command schema and assumes schema is already validated.
193      *
194      * @throws OnapCommandException
195      *
196      * @return List of error strings
197      */
198     public List<String> initializeSchema(String schema) throws OnapCommandException {
199         return this.initializeSchema(schema, false);
200     }
201
202     public List<String> initializeSchema(OnapCommandSchemaInfo schema) throws OnapCommandException {
203         return this.initializeSchema(schema.getSchemaName(), false);
204     }
205
206     public List<String> initializeSchema(String schema, boolean validate) throws OnapCommandException {
207         this.setSchemaName(schema);
208
209         Map<String, ?> schemaMap = OnapCommandSchemaMerger.mergeSchemas(this);
210         List<String> errors = OnapCommandSchemaLoader.parseSchema(this, schemaMap, validate);
211         errors.addAll(this.initializeProfileSchema(schemaMap, validate));
212         this.isInitialzied = true;
213
214         return errors;
215     }
216     /**
217      * Any additional profile based such as http schema could be initialized.
218      */
219     protected List<String> initializeProfileSchema(Map<String, ?> schemaMap, boolean validate) throws OnapCommandException {
220         return new ArrayList<>();
221     }
222
223     /*
224      * Validate input parameters. This can be overridden in derived commands
225      */
226     protected void validate() throws OnapCommandException {
227         for (OnapCommandParameter param : this.getParameters()) {
228              if (param.isInclude()) {
229                  param.validate();
230              }
231          }
232     }
233
234     protected void preRun() throws OnapCommandException {
235         log.debug(this.getName() + " PRE-RUN");
236     }
237
238     protected void postRun() throws OnapCommandException {
239         log.debug(this.getName() + " POST-RUN");
240     }
241
242     /**
243      * Oclip command execute with given parameters on service. Before calling this method, its mandatory to set all
244      * parameters value.
245      *
246      * @throws OnapCommandException
247      *             : General Command Exception
248      */
249     public OnapCommandResult execute() throws OnapCommandException {
250         if (!this.isInitialzied) {
251             throw new OnapCommandNotInitialized(this.getClass().getName());
252         }
253
254         log.info("CMD: " + this.getName());
255
256         Map<String, OnapCommandParameter> paramMap = this.getParametersMap();
257
258         log.info("INPUT: " + paramMap);
259
260         // -h or --help is always higher precedence !, user can set this value to get help message
261         if ((Boolean)(paramMap.get(OnapCommandConstants.DEFAULT_PARAMETER_HELP).getValue())) {
262             this.cmdResult.setType(OnapCommandResultType.TEXT);
263             this.cmdResult.setOutput(this.printHelp());
264             return this.cmdResult;
265         }
266
267         // -v or --version is next higher precedence !, user can set this value to get help message
268         if ((Boolean)(paramMap.get(OnapCommandConstants.DEFAULT_PARAMETER_VERSION).getValue())) {
269             this.cmdResult.setType(OnapCommandResultType.TEXT);
270             this.cmdResult.setOutput(this.printVersion());
271             return this.cmdResult;
272         }
273
274         //set the artifact content path.
275         for (OnapCommandParameter param: this.getParameters()) {
276             if (!param.getParameterType().equals(OnapCommandParameterType.BINARY))
277                 continue;
278
279             if (param.getValue().toString().matches("artifact://*:*")) {
280                 String categoryAndName = param.getValue().toString().replaceFirst("artifact://", "");
281                 String[] categoryAndNameTokens = categoryAndName.split(":");
282                 Artifact a = OnapCommandArtifactStore.getStore().getArtifact(categoryAndNameTokens[1], categoryAndNameTokens[0]);
283                 param.setValue(a.getPath());
284             }
285         }
286
287         // validate
288         this.validate();
289
290         // -f or --format
291         this.cmdResult.setType(
292                 OnapCommandResultType.get(paramMap.get(OnapCommandConstants.DEFAULT_PARAMETER_OUTPUT_FORMAT).getValue().toString()));
293         if ((Boolean)(paramMap.get(OnapCommandConstants.DEFAULT_PARAMETER_OUTPUT_ATTR_LONG).getValue())) {
294             this.cmdResult.setScope(OnapCommandResultAttributeScope.LONG);
295         }
296         // --no-title
297         if ((Boolean)paramMap.get(OnapCommandConstants.DEFAULT_PARAMETER_OUTPUT_NO_TITLE).getValue()) {
298             this.cmdResult.setIncludeTitle(false);
299         }
300
301         // --debug
302         if ((Boolean)(paramMap.get(OnapCommandConstants.DEFAULT_PARAMETER_DEBUG).getValue())) {
303             this.cmdResult.setDebug(true);
304         }
305
306         //pre-process result attributes for spl entries and input parameters
307         for (OnapCommandResultAttribute attr: this.cmdResult.getRecords()) {
308             if (!attr.getDefaultValue().isEmpty()) {
309                 attr.setDefaultValue(OnapCommandUtils.replaceLineForSpecialValues(attr.getDefaultValue()));
310                 attr.setDefaultValue(OnapCommandUtils.replaceLineFromInputParameters(
311                         attr.getDefaultValue(), this.getParametersMap()));
312             }
313         }
314
315         preRun();
316
317         this.run();
318
319         log.info("OUTPUT: " + this.cmdResult.getRecords());
320
321         postRun();
322
323
324         return this.cmdResult;
325     }
326
327     /*
328      * Each command implements run method to executing the command.
329      *
330      */
331     protected abstract void run() throws OnapCommandException;
332
333     /**
334      * Returns the service service version it supports.
335      *
336      * @return version
337      */
338     public String printVersion() {
339         return this.getInfo().getProduct() + "::" + this.getInfo().getService();
340     }
341
342     /**
343      * Provides help message for this command.
344      *
345      * @return help message
346      * @throws OnapCommandHelpFailed
347      *             Failed to execute Help command.
348      */
349     public String printHelp() throws OnapCommandHelpFailed {
350         return OnapCommandHelperUtils.help(this);
351     }
352     // (mrkanag) Add toString for all command, parameter, result, etc objects in JSON format
353
354     public void setExecutionContext(ExecutionStoreContext executionStoreContext) {
355         this.executionStoreContext = executionStoreContext;
356     }
357
358     public ExecutionStoreContext getExecutionContext() {
359         return this.executionStoreContext;
360     }
361 }