Add seed code from Open-O
[cli.git] / framework / src / main / java / org / onap / cli / fw / OnapCommandRegistrar.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;
18
19 import org.onap.cli.fw.cmd.OnapHttpCommand;
20 import org.onap.cli.fw.conf.Constants;
21 import org.onap.cli.fw.conf.OnapCommandConfg;
22 import org.onap.cli.fw.error.OnapCommandException;
23 import org.onap.cli.fw.error.OnapCommandHelpFailed;
24 import org.onap.cli.fw.error.OnapCommandInvalidRegistration;
25 import org.onap.cli.fw.error.OnapCommandNotFound;
26 import org.onap.cli.fw.error.OnapCommandRegistrationFailed;
27 import org.onap.cli.fw.output.OnapCommandResult;
28 import org.onap.cli.fw.output.OnapCommandResultAttribute;
29 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
30 import org.onap.cli.fw.output.PrintDirection;
31 import org.onap.cli.fw.output.ResultType;
32 import org.onap.cli.fw.utils.ExternalSchema;
33 import org.onap.cli.fw.utils.OnapCommandUtils;
34
35 import java.lang.reflect.Constructor;
36 import java.lang.reflect.InvocationTargetException;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Set;
41
42 /**
43  * Onap Command registrar provides a common place, where every command would get registered automatically when its
44  * loaded into JVM.
45  *
46  */
47 public class OnapCommandRegistrar {
48     /*
49      * static { //Start the AOP for logging new OnapCommandLogger(); }
50      */
51     private Map<String, Class<? extends OnapCommand>> registry = new HashMap<>();
52
53     private static OnapCommandRegistrar registrar = null;
54
55     /**
56      * Register the command into registrar and throws OnapInvalidCommandRegistration for invalid command.
57      *
58      * @param name
59      *            Command Name
60      * @param cmd
61      *            Command Class
62      * @throws OnapCommandInvalidRegistration
63      *             Invalid registration exception
64      */
65     public void register(String name, Class<? extends OnapCommand> cmd) throws OnapCommandInvalidRegistration {
66         this.registry.put(name, cmd);
67     }
68
69     /**
70      * Get global registrar.
71      *
72      * @throws OnapCommandException
73      *             exception
74      */
75     public static OnapCommandRegistrar getRegistrar() throws OnapCommandException {
76         if (registrar == null) {
77             registrar = new OnapCommandRegistrar();
78             registrar.autoDiscover();
79             registrar.autoDiscoverHttpSchemas();
80         }
81
82         return registrar;
83     }
84
85     /**
86      * Get the list of discovered commands by registrar.
87      *
88      * @return set
89      */
90     public Set<String> listCommands() {
91         return this.registry.keySet();
92     }
93
94     /**
95      * Returns map of command to schema.
96      *
97      * @return map
98      * @throws OnapCommandException
99      *             exception
100      */
101     public Map<String, String> getAllCommandToSchemaMap() throws OnapCommandException {
102         Map<String, String> map = new HashMap<>();
103         List<ExternalSchema> schemas = OnapCommandUtils.findAllExternalSchemas();
104         if (schemas != null) {
105             for (ExternalSchema schema : schemas) {
106                 map.put(schema.getCmdName(), schema.getSchemaName());
107             }
108         }
109         if (this.registry != null) {
110             for (String cmd : this.registry.keySet()) {
111                 if (!map.containsKey(cmd) && registry.get(cmd) != null) {
112                     map.put(cmd, this.getSchemaFileName(registry.get(cmd)));
113                 }
114             }
115         }
116
117         return map;
118     }
119
120     /**
121      * Get the OnapCommand, which CLI main would use to find the command based on the command name.
122      *
123      * @param cmdName
124      *            Name of command
125      * @return OnapCommand
126      * @throws OnapCommandException
127      *             Exception
128      */
129     public OnapCommand get(String cmdName) throws OnapCommandException {
130         OnapCommand cmd;
131         Class<? extends OnapCommand> cls = registry.get(cmdName);
132         if (cls == null) {
133             throw new OnapCommandNotFound(cmdName);
134         }
135
136         try {
137             Constructor<?> constr = cls.getConstructor();
138             cmd = (OnapCommand) constr.newInstance();
139
140             String schemaName;
141             if (cmd.getClass().equals(OnapHttpCommand.class)) { // NOSONAR
142                 schemaName = OnapCommandUtils.loadExternalSchemaFromJson(cmdName).getSchemaName();
143             } else {
144                 schemaName = this.getSchemaFileName(cls);
145             }
146             cmd.initializeSchema(schemaName);
147         } catch (OnapCommandException | NoSuchMethodException | SecurityException | InstantiationException
148                 | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
149             throw new OnapCommandRegistrationFailed(cmdName, e);
150         }
151
152         return cmd;
153     }
154
155     private void autoDiscover() throws OnapCommandInvalidRegistration {
156         List<Class<OnapCommand>> cmds = OnapCommandUtils.findOnapCommands();
157
158         for (Class<OnapCommand> cmd : cmds) {
159             if (cmd.isAnnotationPresent(OnapCommandSchema.class)) {
160                 OnapCommandSchema ano = cmd.getAnnotation(OnapCommandSchema.class);
161                 this.register(ano.name(), cmd);
162             }
163         }
164     }
165
166     private void autoDiscoverHttpSchemas() throws OnapCommandException {
167         List<ExternalSchema> schemas = OnapCommandUtils.loadExternalSchemasFromJson();
168         for (ExternalSchema schema : schemas) {
169             this.register(schema.getCmdName(), OnapHttpCommand.class);
170         }
171     }
172
173     private String getSchemaFileName(Class<? extends OnapCommand> cmd) {
174         OnapCommandSchema ano = (OnapCommandSchema) cmd.getAnnotation(OnapCommandSchema.class);
175         if (ano.schema().isEmpty()) {
176             return "onap-" + ano.name() + "-schema.yaml";
177         }
178         return ano.schema();
179     }
180
181     /**
182      * Helps to find the Onap CLI version, could be used with --version or -v option.
183      *
184      * @return string
185      */
186     public String getVersion() {
187         String version = this.getClass().getPackage().getImplementationVersion();
188         if (version == null) {
189             version = OnapCommandConfg.getVersion();
190         }
191         return version;
192     }
193
194     /**
195      * Provides the help message in tabular format for all commands registered in this registrar.
196      *
197      * @return string
198      * @throws OnapCommandHelpFailed
199      *             Help cmd failed
200      */
201     public String getHelp() throws OnapCommandHelpFailed {
202         OnapCommandResult help = new OnapCommandResult();
203         help.setType(ResultType.TABLE);
204         help.setPrintDirection(PrintDirection.LANDSCAPE);
205
206         OnapCommandResultAttribute attr = new OnapCommandResultAttribute();
207         attr.setName(Constants.NAME.toUpperCase());
208         attr.setDescription(Constants.DESCRIPTION);
209         attr.setScope(OnapCommandResultAttributeScope.SHORT);
210         help.getRecords().add(attr);
211
212         OnapCommandResultAttribute attrSrv = new OnapCommandResultAttribute();
213         attrSrv.setName(Constants.SERVICE.toUpperCase());
214         attrSrv.setDescription(Constants.SERVICE);
215         attrSrv.setScope(OnapCommandResultAttributeScope.SHORT);
216         help.getRecords().add(attrSrv);
217
218         OnapCommandResultAttribute attrDesc = new OnapCommandResultAttribute();
219         attrDesc.setName(Constants.DESCRIPTION.toUpperCase());
220         attrDesc.setDescription(Constants.DESCRIPTION);
221         attrDesc.setScope(OnapCommandResultAttributeScope.SHORT);
222         help.getRecords().add(attrDesc);
223
224         for (String cmdName : OnapCommandUtils.sort(this.listCommands())) {
225             OnapCommand cmd;
226             try {
227                 cmd = this.get(cmdName);
228             } catch (OnapCommandException e) {
229                 throw new OnapCommandHelpFailed(e);
230             }
231
232             attr.getValues().add(cmd.getName());
233             attrSrv.getValues().add(cmd.printVersion());
234             attrDesc.getValues().add(cmd.getDescription());
235         }
236
237         try {
238             return "\n\nOnap sub-commands:\n" + help.print();
239         } catch (OnapCommandException e) {
240             throw new OnapCommandHelpFailed(e);
241         }
242     }
243 }