Reuse PEM provider in netconf-testtool.
[controller.git] / opendaylight / config / yang-jmx-generator / src / main / java / org / opendaylight / controller / config / yangjmxgenerator / ServiceInterfaceEntry.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 package org.opendaylight.controller.config.yangjmxgenerator;
9
10 import com.google.common.base.Optional;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.Module;
21 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24 import static com.google.common.base.Preconditions.checkNotNull;
25 import static java.lang.String.format;
26 import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.SERVICE_TYPE_Q_NAME;
27
28 /**
29  * Represents identity derived from {@link ConfigConstants#SERVICE_TYPE_Q_NAME}.
30  * Example:
31  * <p>
32  * <blockquote>
33  *
34  * <pre>
35  *  identity eventbus {
36  *  description
37  *  "Service representing an event bus. The service acts as message
38  *  router between event producers and event consumers";
39  *
40  *  base "config:service-type";
41  *  config:java-class "com.google.common.eventbus.EventBus";
42  *  }
43  * </pre>
44  *
45  * </blockquote>
46  * </p>
47  */
48 public class ServiceInterfaceEntry extends AbstractEntry {
49     private static final Logger LOGGER = LoggerFactory
50             .getLogger(ServiceInterfaceEntry.class);
51
52     private static final String CLASS_NAME_SUFFIX = "ServiceInterface";
53     private final Optional<ServiceInterfaceEntry> maybeBaseCache;
54     private final String exportedOsgiClassName;
55     private final QName qName;
56     private final String nullableDescription, packageName, typeName;
57     private final QName yangModuleQName;
58
59     private ServiceInterfaceEntry(IdentitySchemaNode id, String packageName, QName yangModuleQName) {
60         this(Optional.<ServiceInterfaceEntry> absent(), id, packageName, yangModuleQName);
61     }
62
63     private ServiceInterfaceEntry(Optional<ServiceInterfaceEntry> base,
64             IdentitySchemaNode id, String packageName, QName yangModuleQName) {
65         checkNotNull(base);
66         this.maybeBaseCache = base;
67         List<UnknownSchemaNode> unknownSchemaNodes = id.getUnknownSchemaNodes();
68         List<String> exportedOsgiClassNames = new ArrayList<>(
69                 unknownSchemaNodes.size());
70         for (UnknownSchemaNode usn : unknownSchemaNodes) {
71             if (ConfigConstants.JAVA_CLASS_EXTENSION_QNAME.equals(usn
72                     .getNodeType())) {
73                 String localName = usn.getNodeParameter();
74                 exportedOsgiClassNames.add(localName);
75             } else {
76                 throw new IllegalStateException(format(
77                         "Unexpected unknown schema node. Expected %s, got %s",
78                         ConfigConstants.JAVA_CLASS_EXTENSION_QNAME,
79                         usn.getNodeType()));
80             }
81         }
82         if (exportedOsgiClassNames.size() != 1) {
83             throw new IllegalArgumentException(
84                     format("Cannot find one to one mapping from %s to "
85                             + "java class defined by %s language extension in %s",
86                             getClass(),
87                             ConfigConstants.JAVA_CLASS_EXTENSION_QNAME, id));
88         }
89         this.exportedOsgiClassName = exportedOsgiClassNames.get(0);
90         qName = id.getQName();
91         nullableDescription = id.getDescription();
92         typeName = getSimpleName(exportedOsgiClassName) + CLASS_NAME_SUFFIX;
93         this.packageName = packageName;
94         this.yangModuleQName = yangModuleQName;
95     }
96
97     private static final String getSimpleName(String fullyQualifiedName) {
98         int lastDotPosition = fullyQualifiedName.lastIndexOf(".");
99         return fullyQualifiedName.substring(lastDotPosition + 1);
100     }
101
102     public String getNullableDescription() {
103         return nullableDescription;
104     }
105
106     public Optional<ServiceInterfaceEntry> getBase() {
107         return maybeBaseCache;
108     }
109
110     public String getExportedOsgiClassName() {
111         return exportedOsgiClassName;
112     }
113
114     public QName getQName() {
115         return qName;
116     }
117
118     /**
119      * @return Map of QNames as keys and ServiceInterfaceEntry instances as
120      *         values
121      */
122     public static Map<QName, ServiceInterfaceEntry> create(Module currentModule,
123             String packageName,Map<IdentitySchemaNode, ServiceInterfaceEntry> definedSEItracker) {
124         LOGGER.debug("Generating ServiceInterfaces from {} to package {}",
125                 currentModule.getNamespace(), packageName);
126
127         Map<IdentitySchemaNode, ServiceInterfaceEntry> identitiesToSIs = new HashMap<>();
128         Set<IdentitySchemaNode> notVisited = new HashSet<>(
129                 currentModule.getIdentities());
130         int lastSize = notVisited.size() + 1;
131         while (!notVisited.isEmpty()) {
132             if (notVisited.size() == lastSize) {
133                 LOGGER.debug(
134                         "Following identities will be ignored while generating ServiceInterfaces, as they are not derived from {} : {}",
135                         SERVICE_TYPE_Q_NAME, notVisited);
136                 break;
137             }
138             lastSize = notVisited.size();
139             for (Iterator<IdentitySchemaNode> iterator = notVisited.iterator(); iterator
140                     .hasNext();) {
141                 IdentitySchemaNode identity = iterator.next();
142                 ServiceInterfaceEntry created = null;
143                 if (identity.getBaseIdentity() == null) {
144                     // this can happen while loading config module, just skip
145                     // the identity
146                     continue;
147                 } else if (identity.getBaseIdentity().getQName()
148                         .equals(SERVICE_TYPE_Q_NAME)) {
149                     // this is a base type
150                     created = new ServiceInterfaceEntry(identity, packageName, ModuleUtil.getQName(currentModule));
151                 } else {
152                     ServiceInterfaceEntry foundBase = definedSEItracker
153                             .get(identity.getBaseIdentity());
154                     // derived type, did we convert the parent?
155                     if (foundBase != null) {
156                         created = new ServiceInterfaceEntry(
157                                 Optional.of(foundBase), identity, packageName, ModuleUtil.getQName(currentModule));
158                     }
159                 }
160
161
162                 if (created != null) {
163                     created.setYangModuleName(currentModule.getName());
164                     // TODO how to get local name
165                     created.setYangModuleLocalname(identity.getQName()
166                             .getLocalName());
167                     identitiesToSIs.put(identity, created);
168                     definedSEItracker.put(identity, created);
169                     iterator.remove();
170                 }
171             }
172         }
173         // create result map
174         Map<QName, ServiceInterfaceEntry> resultMap = new HashMap<>();
175         for (ServiceInterfaceEntry sie : identitiesToSIs.values()) {
176             resultMap.put(sie.getQName(), sie);
177         }
178         LOGGER.debug("Number of ServiceInterfaces to be generated: {}",
179                 resultMap.size());
180         return resultMap;
181     }
182
183     public String getFullyQualifiedName() {
184         return packageName + "." + typeName;
185     }
186
187     public String getPackageName() {
188         return packageName;
189     }
190
191     public String getTypeName() {
192         return typeName;
193     }
194
195     public QName getYangModuleQName() {
196         return yangModuleQName;
197     }
198
199     @Override
200     public boolean equals(Object o) {
201         if (this == o) {
202             return true;
203         }
204         if (o == null || getClass() != o.getClass()) {
205             return false;
206         }
207
208         ServiceInterfaceEntry that = (ServiceInterfaceEntry) o;
209
210         if (!maybeBaseCache.equals(that.maybeBaseCache)) {
211             return false;
212         }
213         if (!nullableDescription.equals(that.nullableDescription)) {
214             return false;
215         }
216         if (!exportedOsgiClassName.equals(that.exportedOsgiClassName)) {
217             return false;
218         }
219         if (!qName.equals(that.qName)) {
220             return false;
221         }
222         if (!packageName.equals(that.packageName)) {
223             return false;
224         }
225         if (!typeName.equals(that.typeName)) {
226             return false;
227         }
228
229         return true;
230     }
231
232     @Override
233     public int hashCode() {
234         int result = maybeBaseCache.hashCode();
235         result = 31 * result + exportedOsgiClassName.hashCode();
236         result = 31 * result + nullableDescription.hashCode();
237         result = 31 * result + typeName.hashCode();
238         result = 31 * result + packageName.hashCode();
239         result = 31 * result + qName.hashCode();
240         return result;
241     }
242
243     @Override
244     public String toString() {
245         return "ServiceInterfaceEntry{" + "maybeBaseCache=" + maybeBaseCache
246                 + ", qName='" + qName + '\'' + ", fullyQualifiedName='"
247                 + getFullyQualifiedName() + '\'' + ", exportedOsgiClassName="
248                 + exportedOsgiClassName + ", nullableDescription='"
249                 + nullableDescription + '\'' + '}';
250     }
251 }