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 com.google.common.base.Preconditions.checkState;
12 import static java.lang.String.format;
13 import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
15 import java.util.Arrays;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.HashMap;
20 import java.util.Map.Entry;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
25 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
26 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
27 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
28 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
29 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
30 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
31 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
32 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
35 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
36 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
37 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
38 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
39 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
42 import org.opendaylight.yangtools.yang.model.api.Module;
43 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
44 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
45 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
46 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
47 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
48 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.UsesNode;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 import com.google.common.annotations.VisibleForTesting;
54 import com.google.common.collect.Sets;
57 * Represents part of yang model that describes a module.
64 * identity threadpool-dynamic {
65 * base config:module-type;
66 * description "threadpool-dynamic description";
67 * config:provided-service "th2:threadpool";
68 * config:provided-service "th2:scheduled-threadpool";
69 * config:java-name-prefix DynamicThreadPool
71 * augment "/config:modules/config:module/config:module-type" {
72 * case threadpool-dynamic {
73 * when "/config:modules/config:module/config:module-type = 'threadpool-dynamic'";
75 * container "configuration" {
76 * // regular java attribute
83 * container threadfactory {
84 * uses config:service-ref {
86 * config:required-identity th:threadfactory;
97 public class ModuleMXBeanEntry extends AbstractEntry {
98 private static final Logger logger = LoggerFactory
99 .getLogger(ModuleMXBeanEntry.class);
101 // TODO: the XPath should be parsed by code generator IMO
102 private static final String MAGIC_STRING = "MAGIC_STRING";
103 private static final String MODULE_CONDITION_XPATH_TEMPLATE = "^/MAGIC_STRING:modules/MAGIC_STRING:module/MAGIC_STRING:type\\s*=\\s*['\"](.+)['\"]$";
104 private static final SchemaPath expectedConfigurationAugmentationSchemaPath = new SchemaPath(
105 Arrays.asList(createConfigQName("modules"),
106 createConfigQName("module"),
107 createConfigQName("configuration")), true);
108 private static final SchemaPath expectedStateAugmentationSchemaPath = new SchemaPath(
109 Arrays.asList(createConfigQName("modules"),
110 createConfigQName("module"), createConfigQName("state")),
113 private static final Pattern PREFIX_COLON_LOCAL_NAME = Pattern
114 .compile("^(.+):(.+)$");
116 private static final String MODULE_SUFFIX = "Module";
117 private static final String FACTORY_SUFFIX = MODULE_SUFFIX + "Factory";
118 private static final String CLASS_NAME_SUFFIX = MODULE_SUFFIX + "MXBean";
119 private static final String ABSTRACT_PREFIX = "Abstract";
122 * threadpool-dynamic from the example above, taken from when condition, not
125 private final String globallyUniqueName;
127 private Map<String, AttributeIfc> yangToAttributes;
129 private final String nullableDescription, packageName, javaNamePrefix,
132 private final Map<String /* java fully qualified name */, String/* identity local name */> providedServices;
134 private Collection<RuntimeBeanEntry> runtimeBeans;
136 public ModuleMXBeanEntry(IdentitySchemaNode id,
137 Map<String, AttributeIfc> yangToAttributes, String packageName,
138 Map<String, String> providedServices2, String javaNamePrefix,
139 String namespace, Collection<RuntimeBeanEntry> runtimeBeans) {
140 this.globallyUniqueName = id.getQName().getLocalName();
141 this.yangToAttributes = yangToAttributes;
142 this.nullableDescription = id.getDescription();
143 this.packageName = packageName;
144 this.javaNamePrefix = checkNotNull(javaNamePrefix);
145 this.namespace = checkNotNull(namespace);
146 this.providedServices = Collections.unmodifiableMap(providedServices2);
147 this.runtimeBeans = runtimeBeans;
150 public String getMXBeanInterfaceName() {
151 return javaNamePrefix + CLASS_NAME_SUFFIX;
154 public String getStubFactoryName() {
155 return javaNamePrefix + FACTORY_SUFFIX;
158 public String getAbstractFactoryName() {
159 return ABSTRACT_PREFIX + getStubFactoryName();
162 public String getStubModuleName() {
163 return javaNamePrefix + MODULE_SUFFIX;
166 public String getAbstractModuleName() {
167 return ABSTRACT_PREFIX + getStubModuleName();
170 public String getFullyQualifiedName(String typeName) {
171 return FullyQualifiedNameHelper.getFullyQualifiedName(packageName,
175 public String getGloballyUniqueName() {
176 return globallyUniqueName;
179 public String getPackageName() {
184 * @return services implemented by this module. Keys are fully qualified java names of generated
185 * ServiceInterface classes, values are identity local names.
187 public Map<String, String> getProvidedServices() {
188 return providedServices;
191 public void setRuntimeBeans(Collection<RuntimeBeanEntry> newRuntimeBeans) {
192 runtimeBeans = newRuntimeBeans;
195 public Collection<RuntimeBeanEntry> getRuntimeBeans() {
199 public String getJavaNamePrefix() {
200 return javaNamePrefix;
203 public String getNamespace() {
208 static Matcher getWhenConditionMatcher(String prefix,
209 RevisionAwareXPath whenConstraint) {
210 String xpathRegex = MODULE_CONDITION_XPATH_TEMPLATE.replace(
211 MAGIC_STRING, prefix);
212 Pattern pattern = Pattern.compile(xpathRegex);
213 return pattern.matcher(whenConstraint.toString());
216 static String getConfigModulePrefixFromImport(Module currentModule) {
217 for (ModuleImport currentImport : currentModule.getImports()) {
218 if (currentImport.getModuleName().equals(
219 ConfigConstants.CONFIG_MODULE)) {
220 return currentImport.getPrefix();
223 throw new IllegalArgumentException("Cannot find import "
224 + ConfigConstants.CONFIG_MODULE + " in " + currentModule);
228 * Transform module to zero or more ModuleMXBeanEntry instances. Each
229 * instance must have a globally unique local name.
231 * @return Map of identity local names as keys, and ModuleMXBeanEntry
232 * instances as values
234 public static Map<String/* identity local name */, ModuleMXBeanEntry> create(
235 Module currentModule,
236 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
237 SchemaContext schemaContext,
238 TypeProviderWrapper typeProviderWrapper, String packageName) {
239 Map<String, QName> uniqueGeneratedClassesNames = new HashMap<>();
240 logger.debug("Generating ModuleMXBeans of {} to package {}",
241 currentModule.getNamespace(), packageName);
242 String configModulePrefix;
244 configModulePrefix = getConfigModulePrefixFromImport(currentModule);
245 } catch (IllegalArgumentException e) {
246 // this module does not import config module
247 return Collections.emptyMap();
250 // get identities of base config:module-type
251 Map<String, IdentitySchemaNode> moduleIdentities = new HashMap<>();
253 for (IdentitySchemaNode id : currentModule.getIdentities()) {
254 if (id.getBaseIdentity() != null
255 && ConfigConstants.MODULE_TYPE_Q_NAME.equals(id
256 .getBaseIdentity().getQName())) {
257 String identityLocalName = id.getQName().getLocalName();
258 if (moduleIdentities.containsKey(identityLocalName)) {
259 throw new IllegalStateException(
260 "Module name already defined in this module: "
261 + identityLocalName);
263 moduleIdentities.put(identityLocalName, id);
264 logger.debug("Found identity {}", identityLocalName);
266 // validation check on unknown schema nodes
267 boolean providedServiceWasSet = false;
268 for (UnknownSchemaNode unknownNode : id.getUnknownSchemaNodes()) {
270 if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME
271 .equals(unknownNode.getNodeType())) {
272 // no op: 0 or more provided identities are allowed
273 } else if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME
274 .equals(unknownNode.getNodeType())) {
277 providedServiceWasSet == false,
278 format("More than one language extension %s is not allowed here: %s",
279 ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME,
281 providedServiceWasSet = true;
283 throw new IllegalStateException(
284 "Unexpected language extension "
285 + unknownNode.getNodeType());
290 Map<String, ModuleMXBeanEntry> result = new HashMap<>();
291 // each module name should have an augmentation defined
292 Map<String, IdentitySchemaNode> unaugmentedModuleIdentities = new HashMap<>(
294 for (AugmentationSchema augmentation : currentModule.getAugmentations()) {
295 Set<DataSchemaNode> childNodes = augmentation.getChildNodes();
296 if (childNodes.size() == 1) {
297 DataSchemaNode when = childNodes.iterator().next();
298 if (when instanceof ChoiceCaseNode) {
299 ChoiceCaseNode choiceCaseNode = (ChoiceCaseNode) when;
300 if (choiceCaseNode.getConstraints() == null
301 || choiceCaseNode.getConstraints()
302 .getWhenCondition() == null) {
305 RevisionAwareXPath xPath = choiceCaseNode.getConstraints()
307 Matcher matcher = getWhenConditionMatcher(
308 configModulePrefix, xPath);
309 if (matcher.matches() == false) {
312 String moduleLocalNameFromXPath = matcher.group(1);
313 IdentitySchemaNode moduleIdentity = moduleIdentities
314 .get(moduleLocalNameFromXPath);
315 unaugmentedModuleIdentities
316 .remove(moduleLocalNameFromXPath);
317 checkState(moduleIdentity != null, "Cannot find identity "
318 + moduleLocalNameFromXPath
319 + " matching augmentation " + augmentation);
320 Map<String, String> providedServices = findProvidedServices(
321 moduleIdentity, currentModule, qNamesToSIEs,
324 if (moduleIdentity == null) {
325 throw new IllegalStateException(
326 "Cannot find identity specified by augmentation xpath constraint: "
327 + moduleLocalNameFromXPath + " of "
330 String javaNamePrefix = findJavaNamePrefix(moduleIdentity);
332 Map<String, AttributeIfc> yangToAttributes = null;
334 Collection<RuntimeBeanEntry> runtimeBeans = null;
336 if (expectedConfigurationAugmentationSchemaPath
337 .equals(augmentation.getTargetPath())) {
338 logger.debug("Parsing configuration of {}",
339 moduleLocalNameFromXPath);
340 yangToAttributes = fillConfiguration(choiceCaseNode,
341 currentModule, typeProviderWrapper,
342 qNamesToSIEs, schemaContext);
343 checkUniqueAttributesWithGeneratedClass(
344 uniqueGeneratedClassesNames, when.getQName(),
346 } else if (expectedStateAugmentationSchemaPath
347 .equals(augmentation.getTargetPath())) {
348 logger.debug("Parsing state of {}",
349 moduleLocalNameFromXPath);
351 runtimeBeans = fillRuntimeBeans(choiceCaseNode,
352 currentModule, typeProviderWrapper,
353 packageName, moduleLocalNameFromXPath,
355 } catch (NameConflictException e) {
356 throw new NameConflictException(
357 e.getConflictingName(), when.getQName(),
361 checkUniqueRuntimeBeansGeneratedClasses(
362 uniqueGeneratedClassesNames, when, runtimeBeans);
363 Set<RuntimeBeanEntry> runtimeBeanEntryValues = Sets
364 .newHashSet(runtimeBeans);
365 for (RuntimeBeanEntry entry : runtimeBeanEntryValues) {
366 checkUniqueAttributesWithGeneratedClass(
367 uniqueGeneratedClassesNames,
369 entry.getYangPropertiesToTypesMap());
373 throw new IllegalArgumentException(
374 "Cannot parse augmentation " + augmentation);
376 if (result.containsKey(moduleLocalNameFromXPath)) {
377 // either fill runtimeBeans or yangToAttributes
378 ModuleMXBeanEntry moduleMXBeanEntry = result
379 .get(moduleLocalNameFromXPath);
380 if (yangToAttributes != null
381 && moduleMXBeanEntry.getAttributes() == null) {
383 .setYangToAttributes(yangToAttributes);
384 } else if (runtimeBeans != null
385 && moduleMXBeanEntry.getRuntimeBeans() == null) {
386 moduleMXBeanEntry.setRuntimeBeans(runtimeBeans);
389 // construct ModuleMXBeanEntry
390 ModuleMXBeanEntry moduleMXBeanEntry = new ModuleMXBeanEntry(
391 moduleIdentity, yangToAttributes, packageName,
392 providedServices, javaNamePrefix, currentModule
393 .getNamespace().toString(),
395 moduleMXBeanEntry.setYangModuleName(currentModule
398 .setYangModuleLocalname(moduleLocalNameFromXPath);
399 result.put(moduleLocalNameFromXPath, moduleMXBeanEntry);
401 } // skip if child node is not ChoiceCaseNode
402 } // skip if childNodes != 1
405 for (Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
406 ModuleMXBeanEntry module = entry.getValue();
407 if (module.getAttributes() == null) {
408 module.setYangToAttributes(Collections
409 .<String, AttributeIfc> emptyMap());
410 } else if (module.getRuntimeBeans() == null) {
411 module.setRuntimeBeans(Collections
412 .<RuntimeBeanEntry> emptyList());
415 if (unaugmentedModuleIdentities.size() > 0) {
416 logger.warn("Augmentation not found for all module identities: {}",
417 unaugmentedModuleIdentities.keySet());
420 logger.debug("Number of ModuleMXBeans to be generated: {}",
425 private static void checkUniqueRuntimeBeansGeneratedClasses(
426 Map<String, QName> uniqueGeneratedClassesNames,
427 DataSchemaNode when, Collection<RuntimeBeanEntry> runtimeBeans) {
428 for (RuntimeBeanEntry runtimeBean : runtimeBeans) {
429 final String javaNameOfRuntimeMXBean = runtimeBean
430 .getJavaNameOfRuntimeMXBean();
431 if (uniqueGeneratedClassesNames
432 .containsKey(javaNameOfRuntimeMXBean)) {
433 QName firstDefinedQName = uniqueGeneratedClassesNames
434 .get(javaNameOfRuntimeMXBean);
435 throw new NameConflictException(javaNameOfRuntimeMXBean,
436 firstDefinedQName, when.getQName());
438 uniqueGeneratedClassesNames.put(javaNameOfRuntimeMXBean,
443 private static void checkUniqueAttributesWithGeneratedClass(
444 Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
445 Map<String, AttributeIfc> yangToAttributes) {
446 for (Entry<String, AttributeIfc> attr : yangToAttributes.entrySet()) {
447 if (attr.getValue() instanceof TOAttribute) {
448 checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName,
449 (TOAttribute) attr.getValue());
450 } else if (attr.getValue() instanceof ListAttribute
451 && ((ListAttribute) attr.getValue()).getInnerAttribute() instanceof TOAttribute) {
452 checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName,
453 (TOAttribute) ((ListAttribute) attr.getValue())
454 .getInnerAttribute());
459 private static void checkUniqueTOAttr(
460 Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
462 final String upperCaseCammelCase = attr.getUpperCaseCammelCase();
463 if (uniqueGeneratedClassNames.containsKey(upperCaseCammelCase)) {
464 QName firstDefinedQName = uniqueGeneratedClassNames
465 .get(upperCaseCammelCase);
466 throw new NameConflictException(upperCaseCammelCase,
467 firstDefinedQName, parentQName);
469 uniqueGeneratedClassNames.put(upperCaseCammelCase, parentQName);
473 private static Collection<RuntimeBeanEntry> fillRuntimeBeans(
474 ChoiceCaseNode choiceCaseNode, Module currentModule,
475 TypeProviderWrapper typeProviderWrapper, String packageName,
476 String moduleLocalNameFromXPath, String javaNamePrefix) {
478 return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName,
479 choiceCaseNode, moduleLocalNameFromXPath, typeProviderWrapper,
480 javaNamePrefix, currentModule).values();
484 private static Map<String, AttributeIfc> fillConfiguration(
485 ChoiceCaseNode choiceCaseNode, Module currentModule,
486 TypeProviderWrapper typeProviderWrapper,
487 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
488 SchemaContext schemaContext) {
489 Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
490 for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) {
491 AttributeIfc attributeValue = getAttributeValue(attrNode,
492 currentModule, qNamesToSIEs, typeProviderWrapper,
494 yangToAttributes.put(attributeValue.getAttributeYangName(),
497 return yangToAttributes;
500 private static Map<String, String> findProvidedServices(
501 IdentitySchemaNode moduleIdentity, Module currentModule,
502 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
503 SchemaContext schemaContext) {
504 Map<String, String> result = new HashMap<>();
505 for (UnknownSchemaNode unknownNode : moduleIdentity
506 .getUnknownSchemaNodes()) {
507 if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME
508 .equals(unknownNode.getNodeType())) {
509 String prefixAndIdentityLocalName = unknownNode
511 ServiceInterfaceEntry sie = findSIE(prefixAndIdentityLocalName,
512 currentModule, qNamesToSIEs, schemaContext);
513 result.put(sie.getFullyQualifiedName(), sie.getQName()
521 * For input node, find if it contains config:java-name-prefix extension. If
522 * not found, convert local name of node converted to cammel case.
524 public static String findJavaNamePrefix(SchemaNode schemaNode) {
525 return convertToJavaName(schemaNode, true);
528 public static String findJavaParameter(SchemaNode schemaNode) {
529 return convertToJavaName(schemaNode, false);
532 public static String convertToJavaName(SchemaNode schemaNode,
533 boolean capitalizeFirstLetter) {
534 for (UnknownSchemaNode unknownNode : schemaNode.getUnknownSchemaNodes()) {
535 if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME
536 .equals(unknownNode.getNodeType())) {
537 String value = unknownNode.getNodeParameter();
538 return convertToJavaName(value, capitalizeFirstLetter);
541 return convertToJavaName(schemaNode.getQName().getLocalName(),
542 capitalizeFirstLetter);
545 public static String convertToJavaName(String localName,
546 boolean capitalizeFirstLetter) {
547 if (capitalizeFirstLetter) {
548 return BindingGeneratorUtil.parseToClassName(localName);
550 return BindingGeneratorUtil.parseToValidParamName(localName);
554 private static int getChildNodeSizeWithoutUses(ContainerSchemaNode csn) {
556 for (DataSchemaNode dsn : csn.getChildNodes()) {
557 if (dsn.isAddedByUses() == false)
563 private static AttributeIfc getAttributeValue(DataSchemaNode attrNode,
564 Module currentModule,
565 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
566 TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext) {
568 if (attrNode instanceof LeafSchemaNode) {
570 LeafSchemaNode leaf = (LeafSchemaNode) attrNode;
571 return new JavaAttribute(leaf, typeProviderWrapper);
572 } else if (attrNode instanceof ContainerSchemaNode) {
574 ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
575 if (containerSchemaNode.getUses().size() == 1
576 && getChildNodeSizeWithoutUses(containerSchemaNode) == 0) {
578 UsesNode usesNode = containerSchemaNode.getUses().iterator()
580 checkState(usesNode.getRefines().size() == 1,
581 "Unexpected 'refine' child node size of "
582 + containerSchemaNode);
583 LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines()
584 .values().iterator().next();
585 checkState(refine.getUnknownSchemaNodes().size() == 1,
586 "Unexpected unknown schema node size of " + refine);
587 UnknownSchemaNode requiredIdentity = refine
588 .getUnknownSchemaNodes().iterator().next();
590 ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity
592 "Unexpected language extension " + requiredIdentity);
593 String prefixAndIdentityLocalName = requiredIdentity
595 // import should point to a module
596 ServiceInterfaceEntry serviceInterfaceEntry = findSIE(
597 prefixAndIdentityLocalName, currentModule,
598 qNamesToSIEs, schemaContext);
599 boolean mandatory = refine.getConstraints().isMandatory();
600 return new DependencyAttribute(attrNode, serviceInterfaceEntry,
601 mandatory, attrNode.getDescription());
603 return TOAttribute.create(containerSchemaNode,
604 typeProviderWrapper);
606 } else if (attrNode instanceof LeafListSchemaNode) {
607 return ListAttribute.create((LeafListSchemaNode) attrNode,
608 typeProviderWrapper);
609 } else if (attrNode instanceof ListSchemaNode) {
610 return ListAttribute.create((ListSchemaNode) attrNode,
611 typeProviderWrapper);
613 throw new UnsupportedOperationException(
614 "Unknown configuration node " + attrNode.toString());
618 private static ServiceInterfaceEntry findSIE(
619 String prefixAndIdentityLocalName, Module currentModule,
620 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
621 SchemaContext schemaContext) {
623 Matcher m = PREFIX_COLON_LOCAL_NAME.matcher(prefixAndIdentityLocalName);
627 // if there is a prefix, look for ModuleImport with this prefix. Get
628 // Module from SchemaContext
629 String prefix = m.group(1);
630 ModuleImport moduleImport = findModuleImport(currentModule, prefix);
631 foundModule = schemaContext.findModuleByName(
632 moduleImport.getModuleName(), moduleImport.getRevision());
635 format("Module not found in SchemaContext by %s",
637 localSIName = m.group(2);
639 foundModule = currentModule; // no prefix => SIE is in currentModule
640 localSIName = prefixAndIdentityLocalName;
642 QName siQName = new QName(foundModule.getNamespace(),
643 foundModule.getRevision(), localSIName);
644 ServiceInterfaceEntry sie = qNamesToSIEs.get(siQName);
645 checkState(sie != null, "Cannot find referenced Service Interface by "
646 + prefixAndIdentityLocalName);
650 private static ModuleImport findModuleImport(Module module, String prefix) {
651 for (ModuleImport moduleImport : module.getImports()) {
652 if (moduleImport.getPrefix().equals(prefix)) {
656 throw new IllegalStateException(format(
657 "Import not found with prefix %s in %s", prefix, module));
660 public Map<String, AttributeIfc> getAttributes() {
661 return yangToAttributes;
664 private void setYangToAttributes(Map<String, AttributeIfc> newAttributes) {
665 this.yangToAttributes = newAttributes;
669 public String getNullableDescription() {
670 return nullableDescription;
674 public String toString() {
675 return "ModuleMXBeanEntry{" + "globallyUniqueName='"
676 + globallyUniqueName + '\'' + ", packageName='" + packageName