2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.config.yangjmxgenerator;
10 import static com.google.common.base.Preconditions.checkNotNull;
11 import static java.lang.String.format;
12 import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.SERVICE_TYPE_Q_NAME;
14 import com.google.common.base.Optional;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.List;
22 import org.opendaylight.yangtools.yang.common.QName;
23 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.Module;
25 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Represents identity derived from {@link ConfigConstants#SERVICE_TYPE_Q_NAME}.
38 * "Service representing an event bus. The service acts as message
39 * router between event producers and event consumers";
41 * base "config:service-type";
42 * config:java-class "com.google.common.eventbus.EventBus";
48 public class ServiceInterfaceEntry extends AbstractEntry {
49 private static final Logger LOG = LoggerFactory
50 .getLogger(ServiceInterfaceEntry.class);
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 private final boolean registerToOsgi;
60 private ServiceInterfaceEntry(final IdentitySchemaNode id, final String packageName, final QName yangModuleQName) {
61 this(Optional.<ServiceInterfaceEntry> absent(), id, packageName, yangModuleQName);
64 private ServiceInterfaceEntry(final Optional<ServiceInterfaceEntry> base,
65 final IdentitySchemaNode id, final String packageName, final QName yangModuleQName) {
67 this.maybeBaseCache = base;
68 List<UnknownSchemaNode> unknownSchemaNodes = id.getUnknownSchemaNodes();
69 List<String> exportedOsgiClassNames = new ArrayList<>(
70 unknownSchemaNodes.size());
72 boolean disableOsgiServiceRegistration = false;
73 for (UnknownSchemaNode usn : unknownSchemaNodes) {
74 if (ConfigConstants.JAVA_CLASS_EXTENSION_QNAME.equals(usn.getNodeType())) {
75 String localName = usn.getNodeParameter();
76 exportedOsgiClassNames.add(localName);
77 } else if (ConfigConstants.DISABLE_OSGI_SERVICE_REG_QNAME.equals(usn.getNodeType())) {
78 disableOsgiServiceRegistration = true;
80 throw new IllegalStateException(format(
81 "Unexpected unknown schema node. Expected %s, got %s",
82 ConfigConstants.JAVA_CLASS_EXTENSION_QNAME,
86 if (exportedOsgiClassNames.size() != 1) {
87 throw new IllegalArgumentException(
88 format("Cannot find one to one mapping from %s to "
89 + "java class defined by %s language extension in %s",
91 ConfigConstants.JAVA_CLASS_EXTENSION_QNAME, id));
94 this.registerToOsgi = !disableOsgiServiceRegistration;
95 this.exportedOsgiClassName = exportedOsgiClassNames.get(0);
96 qName = id.getQName();
97 nullableDescription = id.getDescription().orElse(null);
98 typeName = getSimpleName(exportedOsgiClassName) + CLASS_NAME_SUFFIX;
99 this.packageName = packageName;
100 this.yangModuleQName = yangModuleQName;
103 private static final String getSimpleName(final String fullyQualifiedName) {
104 int lastDotPosition = fullyQualifiedName.lastIndexOf(".");
105 return fullyQualifiedName.substring(lastDotPosition + 1);
108 public String getNullableDescription() {
109 return nullableDescription;
112 public Optional<ServiceInterfaceEntry> getBase() {
113 return maybeBaseCache;
116 public String getExportedOsgiClassName() {
117 return exportedOsgiClassName;
120 public QName getQName() {
124 public boolean isRegisterToOsgi() {
125 return registerToOsgi;
129 * @return Map of QNames as keys and ServiceInterfaceEntry instances as
132 public static Map<QName, ServiceInterfaceEntry> create(final Module currentModule,
133 final String packageName,final Map<IdentitySchemaNode, ServiceInterfaceEntry> definedSEItracker) {
134 LOG.debug("Generating ServiceInterfaces from {} to package {}",
135 currentModule.getNamespace(), packageName);
137 Map<IdentitySchemaNode, ServiceInterfaceEntry> identitiesToSIs = new HashMap<>();
138 Set<IdentitySchemaNode> notVisited = new HashSet<>(
139 currentModule.getIdentities());
140 int lastSize = notVisited.size() + 1;
141 while (!notVisited.isEmpty()) {
142 if (notVisited.size() == lastSize) {
144 "Following identities will be ignored while generating ServiceInterfaces, as they are not derived from {} : {}",
145 SERVICE_TYPE_Q_NAME, notVisited);
148 lastSize = notVisited.size();
149 for (Iterator<IdentitySchemaNode> iterator = notVisited.iterator(); iterator
151 IdentitySchemaNode identity = iterator.next();
152 ServiceInterfaceEntry created = null;
153 if (identity.getBaseIdentities().isEmpty()) {
154 // this can happen while loading config module, just skip
157 } else if (identity.getBaseIdentities().iterator().next().getQName()
158 .equals(SERVICE_TYPE_Q_NAME)) {
159 // this is a base type
160 created = new ServiceInterfaceEntry(identity, packageName, ModuleUtil.getQName(currentModule));
162 ServiceInterfaceEntry foundBase = definedSEItracker
163 .get(identity.getBaseIdentities().iterator().next());
164 // derived type, did we convert the parent?
165 if (foundBase != null) {
166 created = new ServiceInterfaceEntry(
167 Optional.of(foundBase), identity, packageName, ModuleUtil.getQName(currentModule));
172 if (created != null) {
173 created.setYangModuleName(currentModule.getName());
174 // TODO how to get local name
175 created.setYangModuleLocalname(identity.getQName()
177 identitiesToSIs.put(identity, created);
178 definedSEItracker.put(identity, created);
184 Map<QName, ServiceInterfaceEntry> resultMap = new HashMap<>();
185 for (ServiceInterfaceEntry sie : identitiesToSIs.values()) {
186 resultMap.put(sie.getQName(), sie);
188 LOG.debug("Number of ServiceInterfaces to be generated: {}",
193 public String getFullyQualifiedName() {
194 return packageName + "." + typeName;
197 public String getPackageName() {
201 public String getTypeName() {
205 public QName getYangModuleQName() {
206 return yangModuleQName;
210 public boolean equals(final Object o) {
214 if (o == null || getClass() != o.getClass()) {
218 ServiceInterfaceEntry that = (ServiceInterfaceEntry) o;
220 if (!maybeBaseCache.equals(that.maybeBaseCache)) {
223 if (!nullableDescription.equals(that.nullableDescription)) {
226 if (!exportedOsgiClassName.equals(that.exportedOsgiClassName)) {
229 if (!qName.equals(that.qName)) {
232 if (!packageName.equals(that.packageName)) {
235 if (!typeName.equals(that.typeName)) {
243 public int hashCode() {
244 int result = maybeBaseCache.hashCode();
245 result = 31 * result + exportedOsgiClassName.hashCode();
246 result = 31 * result + nullableDescription.hashCode();
247 result = 31 * result + typeName.hashCode();
248 result = 31 * result + packageName.hashCode();
249 result = 31 * result + qName.hashCode();
254 public String toString() {
255 return "ServiceInterfaceEntry{" + "maybeBaseCache=" + maybeBaseCache
256 + ", qName='" + qName + '\'' + ", fullyQualifiedName='"
257 + getFullyQualifiedName() + '\'' + ", exportedOsgiClassName="
258 + exportedOsgiClassName + ", nullableDescription='"
259 + nullableDescription + '\'' + '}';