e7a7d2147e671e527f0b20ede65239c93bd5316a
[controller.git] / opendaylight / config / yang-jmx-generator-plugin / src / main / java / org / opendaylight / controller / config / yangjmxgenerator / plugin / gofactory / AbsFactoryGeneratedObjectFactory.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.config.yangjmxgenerator.plugin.gofactory;
10
11 import static java.lang.String.format;
12
13 import com.google.common.base.Optional;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.controller.config.api.DependencyResolver;
17 import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
18 import org.opendaylight.controller.config.api.ModuleIdentifier;
19 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
20 import org.opendaylight.controller.config.api.annotations.Description;
21 import org.opendaylight.controller.config.spi.Module;
22 import org.opendaylight.controller.config.spi.ModuleFactory;
23 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
24 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.AbstractFactoryTemplate;
25 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.TemplateFactory;
26 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Annotation;
27 import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field;
28 import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.FullyQualifiedName;
29 import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObject;
30 import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.GeneratedObjectBuilder;
31 import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.JavaFileInputBuilder;
32 import org.opendaylight.controller.config.yangjmxgenerator.plugin.java.TypeName;
33 import org.opendaylight.yangtools.yang.common.QName;
34
35 public class AbsFactoryGeneratedObjectFactory {
36     private static final String BUNDLE_CONTEXT = "org.osgi.framework.BundleContext";
37
38     public GeneratedObject toGeneratedObject(ModuleMXBeanEntry mbe, Optional<String> copyright) {
39         FullyQualifiedName absFactoryFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getAbstractFactoryName());
40         FullyQualifiedName moduleFQN = new FullyQualifiedName(mbe.getPackageName(), mbe.getStubModuleName());
41         Optional<String> classJavaDoc = Optional.fromNullable(mbe.getNullableDescription());
42
43         AbstractFactoryTemplate abstractFactoryTemplate = TemplateFactory.abstractFactoryTemplateFromMbe(mbe);
44         Optional<String> header = abstractFactoryTemplate.getHeaderString();
45
46         List<FullyQualifiedName> providedServices = new ArrayList<>();
47         for(String providedService: mbe.getProvidedServices().keySet()) {
48             providedServices.add(FullyQualifiedName.fromString(providedService));
49         }
50
51         return toGeneratedObject(absFactoryFQN, copyright,
52                 header, classJavaDoc, mbe.getYangModuleQName(),
53                 mbe.getGloballyUniqueName(),
54                 providedServices,
55                 moduleFQN,
56                 abstractFactoryTemplate.getFields());
57     }
58
59     public GeneratedObject toGeneratedObject(FullyQualifiedName absFactoryFQN, Optional<String> copyright,
60                                              Optional<String> header, Optional<String> classJavaDoc, QName yangModuleQName,
61                                              String globallyUniqueName,
62                                              List<FullyQualifiedName> providedServices,
63                                              FullyQualifiedName moduleFQN,
64                                              List<Field> moduleFields) {
65         JavaFileInputBuilder b = new JavaFileInputBuilder();
66
67         b.addImportFQN(new FullyQualifiedName(Module.class));
68         b.addImportFQN(new FullyQualifiedName(ModuleIdentifier.class));
69
70         Annotation moduleQNameAnnotation = Annotation.createModuleQNameANnotation(yangModuleQName);
71         b.addClassAnnotation(moduleQNameAnnotation);
72
73         b.setFqn(absFactoryFQN);
74         b.setTypeName(TypeName.absClassType);
75
76         b.setCopyright(copyright);
77         b.setHeader(header);
78         b.setClassJavaDoc(classJavaDoc);
79         b.addImplementsFQN(new FullyQualifiedName(ModuleFactory.class));
80         if (classJavaDoc.isPresent()) {
81             b.addClassAnnotation(format("@%s(value=\"%s\")", Description.class.getCanonicalName(), classJavaDoc.get()));
82         }
83
84         b.addToBody(format("public static final java.lang.String NAME = \"%s\";", globallyUniqueName));
85         b.addToBody(format("private static final java.util.Set<Class<? extends %s>> serviceIfcs;",
86                 AbstractServiceInterface.class.getCanonicalName()));
87
88         b.addToBody("@Override\n public final String getImplementationName() { \n return NAME; \n}");
89
90         b.addToBody(getServiceIfcsInitialization(providedServices));
91
92         // createModule
93         b.addToBody(format("\n"+
94             "@Override\n"+
95             "public %s createModule(String instanceName, %s dependencyResolver, %s bundleContext) {\n"+
96                 "return instantiateModule(instanceName, dependencyResolver, bundleContext);\n"+
97             "}\n",
98                 Module.class.getCanonicalName(), DependencyResolver.class.getCanonicalName(), BUNDLE_CONTEXT));
99
100         b.addToBody(getCreateModule(moduleFQN, moduleFields));
101
102         b.addToBody(format("\n"+
103             "public %s instantiateModule(String instanceName, %s dependencyResolver, %s oldModule, %s oldInstance, %s bundleContext) {\n"+
104                 "return new %s(new %s(NAME, instanceName), dependencyResolver, oldModule, oldInstance);\n"+
105             "}\n",
106                 moduleFQN, DependencyResolver.class.getCanonicalName(), moduleFQN, AutoCloseable.class.getCanonicalName(),
107                 BUNDLE_CONTEXT, moduleFQN, ModuleIdentifier.class.getCanonicalName()));
108
109         b.addToBody(format("\n"+
110             "public %s instantiateModule(String instanceName, %s dependencyResolver, %s bundleContext) {\n"+
111                 "return new %s(new %s(NAME, instanceName), dependencyResolver);\n"+
112             "}\n", moduleFQN, DependencyResolver.class.getCanonicalName(), BUNDLE_CONTEXT,
113                 moduleFQN, ModuleIdentifier.class.getCanonicalName()
114         ));
115
116         b.addToBody(format("\n"+
117                 "public %s handleChangedClass(%s dependencyResolver, %s old, %s bundleContext) throws Exception {\n" +
118                     // "// @Deprecated return handleChangedClass(old);\n" +
119                     "String instanceName = old.getModule().getIdentifier().getInstanceName();\n" +
120                     "%1$s newModule = new %1$s(new ModuleIdentifier(NAME, instanceName), dependencyResolver);\n" +
121                     "Module oldModule = old.getModule();\n" +
122                     "Class<? extends Module> oldModuleClass = oldModule.getClass();\n" +
123                     genCodeToCopyAttributes(moduleFields) +
124                     "return newModule;\n" +
125                 "}\n", moduleFQN, DependencyResolver.class.getCanonicalName(), DynamicMBeanWithInstance.class.getCanonicalName(), BUNDLE_CONTEXT));
126
127         b.addToBody(format("\n@Deprecated\n"+
128             "public %s handleChangedClass(%s old) throws Exception {\n"+
129                 "throw new UnsupportedOperationException(\"Class reloading is not supported\");\n"+
130             "}\n", moduleFQN, DynamicMBeanWithInstance.class.getCanonicalName()));
131
132         b.addToBody(format("\n"+
133             "@Override\n"+
134             "public java.util.Set<%s> getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory dependencyResolverFactory, %s bundleContext) {\n"+
135                 "return new java.util.HashSet<>();\n"+
136             "}\n", moduleFQN, BUNDLE_CONTEXT));
137
138         return new GeneratedObjectBuilder(b.build()).toGeneratedObject();
139     }
140
141     private String genCodeToCopyAttributes(List<Field> moduleFields) {
142         StringBuilder sb = new StringBuilder("\n");
143         for (Field field : moduleFields) {
144             sb.append(format("newModule.set%1$s( (%2$s) oldModuleClass.getMethod(\"get%1$s\").invoke(oldModule));\n", field.getName(), field.getType()));
145         }
146         sb.append('\n');
147         return sb.toString();
148     }
149
150     private static String getCreateModule(FullyQualifiedName moduleFQN, List<Field> moduleFields) {
151         String result = "\n"+
152             "@Override\n"+
153             format("public %s createModule(String instanceName, %s dependencyResolver, %s old, %s bundleContext) throws Exception {\n",
154                                 Module.class.getCanonicalName(), DependencyResolver.class.getCanonicalName(),
155                                 DynamicMBeanWithInstance.class.getCanonicalName(), BUNDLE_CONTEXT)+
156                 format("%s oldModule;\n",moduleFQN)+
157                 "try {\n"+
158                     format("oldModule = (%s) old.getModule();\n", moduleFQN)+
159                 "} catch(Exception e) {\n"+
160                     "return handleChangedClass(dependencyResolver, old, bundleContext);\n"+
161                 "}\n"+
162             format("%s module = instantiateModule(instanceName, dependencyResolver, oldModule, old.getInstance(), bundleContext);\n", moduleFQN);
163
164         for(Field field: moduleFields) {
165             result += format("module.set%s(oldModule.get%1$s());\n", field.getName());
166         }
167
168         result += "\n"+
169                 "return module;\n"+
170             "}\n";
171         return result;
172     }
173
174     private static String getServiceIfcsInitialization(List<FullyQualifiedName> providedServices) {
175         String generic = format("Class<? extends %s>", AbstractServiceInterface.class.getCanonicalName());
176
177         String result = "static {\n";
178         if (!providedServices.isEmpty()) {
179             result += format("java.util.Set<%1$s> serviceIfcs2 = new java.util.HashSet<>();\n", generic);
180
181             for(FullyQualifiedName fqn: providedServices) {
182                 result += format("serviceIfcs2.add(%s.class);\n", fqn);
183             }
184
185             result += "serviceIfcs = java.util.Collections.unmodifiableSet(serviceIfcs2);\n";
186         } else {
187             result += "serviceIfcs = java.util.Collections.emptySet();\n";
188         }
189         result += "}\n";
190
191         // add isModuleImplementingServiceInterface and getImplementedServiceIntefaces methods
192
193         result += format("\n"+
194             "@Override\n"+
195             "public final boolean isModuleImplementingServiceInterface(Class<? extends %1$s> serviceInterface) {\n"+
196                 "for (Class<?> ifc: serviceIfcs) {\n"+
197                     "if (serviceInterface.isAssignableFrom(ifc)){\n"+
198                         "return true;\n"+
199                     "}\n"+
200                 "}\n"+
201                 "return false;\n"+
202             "}\n"+
203             "\n"+
204             "@Override\n"+
205             "public java.util.Set<Class<? extends %1$s>> getImplementedServiceIntefaces() {\n"+
206                 "return serviceIfcs;\n"+
207             "}\n", AbstractServiceInterface.class.getCanonicalName());
208
209         return result;
210     }
211
212 }