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 com.google.common.annotations.VisibleForTesting;
11 import com.google.common.collect.Sets;
12 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
13 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
14 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
15 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
16 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
17 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.FullyQualifiedNameHelper;
18 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
19 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
20 import org.opendaylight.yangtools.yang.common.QName;
21 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
22 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
23 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
26 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.Module;
30 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
31 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
35 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.UsesNode;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 import java.util.Arrays;
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.HashMap;
45 import java.util.Map.Entry;
47 import java.util.regex.Matcher;
48 import java.util.regex.Pattern;
50 import static com.google.common.base.Preconditions.checkNotNull;
51 import static com.google.common.base.Preconditions.checkState;
52 import static java.lang.String.format;
53 import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
56 * Represents part of yang model that describes a module.
63 * identity threadpool-dynamic {
64 * base config:module-type;
65 * description "threadpool-dynamic description";
66 * config:provided-service "th2:threadpool";
67 * config:provided-service "th2:scheduled-threadpool";
68 * config:java-name-prefix DynamicThreadPool
70 * augment "/config:modules/config:module/config:module-type" {
71 * case threadpool-dynamic {
72 * when "/config:modules/config:module/config:module-type = 'threadpool-dynamic'";
74 * container "configuration" {
75 * // regular java attribute
82 * container threadfactory {
83 * uses config:service-ref {
85 * config:required-identity th:threadfactory;
96 public class ModuleMXBeanEntry extends AbstractEntry {
97 private static final Logger logger = LoggerFactory
98 .getLogger(ModuleMXBeanEntry.class);
100 // TODO: the XPath should be parsed by code generator IMO
101 private static final String MAGIC_STRING = "MAGIC_STRING";
102 private static final String MODULE_CONDITION_XPATH_TEMPLATE = "^/MAGIC_STRING:modules/MAGIC_STRING:module/MAGIC_STRING:type\\s*=\\s*['\"](.+)['\"]$";
103 private static final SchemaPath expectedConfigurationAugmentationSchemaPath = new SchemaPath(
104 Arrays.asList(createConfigQName("modules"),
105 createConfigQName("module"),
106 createConfigQName("configuration")), true);
107 private static final SchemaPath expectedStateAugmentationSchemaPath = new SchemaPath(
108 Arrays.asList(createConfigQName("modules"),
109 createConfigQName("module"), createConfigQName("state")),
112 private static final Pattern PREFIX_COLON_LOCAL_NAME = Pattern
113 .compile("^(.+):(.+)$");
115 private static final String MODULE_SUFFIX = "Module";
116 private static final String FACTORY_SUFFIX = MODULE_SUFFIX + "Factory";
117 private static final String CLASS_NAME_SUFFIX = MODULE_SUFFIX + "MXBean";
118 private static final String ABSTRACT_PREFIX = "Abstract";
121 * threadpool-dynamic from the example above, taken from when condition, not
124 private final String globallyUniqueName;
126 private Map<String, AttributeIfc> yangToAttributes;
128 private final String nullableDescription, packageName, javaNamePrefix,
131 private final Map<String, QName> providedServices;
133 private Collection<RuntimeBeanEntry> runtimeBeans;
135 public ModuleMXBeanEntry(IdentitySchemaNode id,
136 Map<String, AttributeIfc> yangToAttributes, String packageName,
137 Map<String, QName> providedServices2, String javaNamePrefix,
138 String namespace, Collection<RuntimeBeanEntry> runtimeBeans) {
139 this.globallyUniqueName = id.getQName().getLocalName();
140 this.yangToAttributes = yangToAttributes;
141 this.nullableDescription = id.getDescription();
142 this.packageName = packageName;
143 this.javaNamePrefix = checkNotNull(javaNamePrefix);
144 this.namespace = checkNotNull(namespace);
145 this.providedServices = Collections.unmodifiableMap(providedServices2);
146 this.runtimeBeans = runtimeBeans;
149 public String getMXBeanInterfaceName() {
150 return javaNamePrefix + CLASS_NAME_SUFFIX;
153 public String getStubFactoryName() {
154 return javaNamePrefix + FACTORY_SUFFIX;
157 public String getAbstractFactoryName() {
158 return ABSTRACT_PREFIX + getStubFactoryName();
161 public String getStubModuleName() {
162 return javaNamePrefix + MODULE_SUFFIX;
165 public String getAbstractModuleName() {
166 return ABSTRACT_PREFIX + getStubModuleName();
169 public String getFullyQualifiedName(String typeName) {
170 return FullyQualifiedNameHelper.getFullyQualifiedName(packageName,
174 public String getGloballyUniqueName() {
175 return globallyUniqueName;
178 public String getPackageName() {
183 * @return services implemented by this module. Keys are fully qualified java names of generated
184 * ServiceInterface classes, values are identity local names.
186 public Map<String, QName> getProvidedServices() {
187 return providedServices;
190 public void setRuntimeBeans(Collection<RuntimeBeanEntry> newRuntimeBeans) {
191 runtimeBeans = newRuntimeBeans;
194 public Collection<RuntimeBeanEntry> getRuntimeBeans() {
198 public String getJavaNamePrefix() {
199 return javaNamePrefix;
202 public String getNamespace() {
207 static Matcher getWhenConditionMatcher(String prefix,
208 RevisionAwareXPath whenConstraint) {
209 String xpathRegex = MODULE_CONDITION_XPATH_TEMPLATE.replace(
210 MAGIC_STRING, prefix);
211 Pattern pattern = Pattern.compile(xpathRegex);
212 return pattern.matcher(whenConstraint.toString());
215 static String getConfigModulePrefixFromImport(Module currentModule) {
216 for (ModuleImport currentImport : currentModule.getImports()) {
217 if (currentImport.getModuleName().equals(
218 ConfigConstants.CONFIG_MODULE)) {
219 return currentImport.getPrefix();
222 throw new IllegalArgumentException("Cannot find import "
223 + ConfigConstants.CONFIG_MODULE + " in " + currentModule);
227 * Transform module to zero or more ModuleMXBeanEntry instances. Each
228 * instance must have a globally unique local name.
230 * @return Map of identity local names as keys, and ModuleMXBeanEntry
231 * instances as values
233 public static Map<String/* identity local name */, ModuleMXBeanEntry> create(
234 Module currentModule,
235 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
236 SchemaContext schemaContext,
237 TypeProviderWrapper typeProviderWrapper, String packageName) {
238 Map<String, QName> uniqueGeneratedClassesNames = new HashMap<>();
239 logger.debug("Generating ModuleMXBeans of {} to package {}",
240 currentModule.getNamespace(), packageName);
241 String configModulePrefix;
243 configModulePrefix = getConfigModulePrefixFromImport(currentModule);
244 } catch (IllegalArgumentException e) {
245 // this module does not import config module
246 return Collections.emptyMap();
249 // get identities of base config:module-type
250 Map<String, IdentitySchemaNode> moduleIdentities = new HashMap<>();
252 for (IdentitySchemaNode id : currentModule.getIdentities()) {
253 if (id.getBaseIdentity() != null
254 && ConfigConstants.MODULE_TYPE_Q_NAME.equals(id
255 .getBaseIdentity().getQName())) {
256 String identityLocalName = id.getQName().getLocalName();
257 if (moduleIdentities.containsKey(identityLocalName)) {
258 throw new IllegalStateException(
259 "Module name already defined in this module: "
260 + identityLocalName);
262 moduleIdentities.put(identityLocalName, id);
263 logger.debug("Found identity {}", identityLocalName);
265 // validation check on unknown schema nodes
266 boolean providedServiceWasSet = false;
267 for (UnknownSchemaNode unknownNode : id.getUnknownSchemaNodes()) {
269 if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME
270 .equals(unknownNode.getNodeType())) {
271 // no op: 0 or more provided identities are allowed
272 } else if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME
273 .equals(unknownNode.getNodeType())) {
276 providedServiceWasSet == false,
277 format("More than one language extension %s is not allowed here: %s",
278 ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME,
280 providedServiceWasSet = true;
282 throw new IllegalStateException(
283 "Unexpected language extension "
284 + unknownNode.getNodeType());
289 Map<String, ModuleMXBeanEntry> result = new HashMap<>();
290 // each module name should have an augmentation defined
291 Map<String, IdentitySchemaNode> unaugmentedModuleIdentities = new HashMap<>(
293 for (AugmentationSchema augmentation : currentModule.getAugmentations()) {
294 Set<DataSchemaNode> childNodes = augmentation.getChildNodes();
295 if (childNodes.size() == 1) {
296 DataSchemaNode when = childNodes.iterator().next();
297 if (when instanceof ChoiceCaseNode) {
298 ChoiceCaseNode choiceCaseNode = (ChoiceCaseNode) when;
299 if (choiceCaseNode.getConstraints() == null
300 || choiceCaseNode.getConstraints()
301 .getWhenCondition() == null) {
304 RevisionAwareXPath xPath = choiceCaseNode.getConstraints()
306 Matcher matcher = getWhenConditionMatcher(
307 configModulePrefix, xPath);
308 if (matcher.matches() == false) {
311 String moduleLocalNameFromXPath = matcher.group(1);
312 IdentitySchemaNode moduleIdentity = moduleIdentities
313 .get(moduleLocalNameFromXPath);
314 unaugmentedModuleIdentities
315 .remove(moduleLocalNameFromXPath);
316 checkState(moduleIdentity != null, "Cannot find identity "
317 + moduleLocalNameFromXPath
318 + " matching augmentation " + augmentation);
319 Map<String, QName> providedServices = findProvidedServices(
320 moduleIdentity, currentModule, qNamesToSIEs,
323 if (moduleIdentity == null) {
324 throw new IllegalStateException(
325 "Cannot find identity specified by augmentation xpath constraint: "
326 + moduleLocalNameFromXPath + " of "
329 String javaNamePrefix = findJavaNamePrefix(moduleIdentity);
331 Map<String, AttributeIfc> yangToAttributes = null;
333 Collection<RuntimeBeanEntry> runtimeBeans = null;
335 if (expectedConfigurationAugmentationSchemaPath
336 .equals(augmentation.getTargetPath())) {
337 logger.debug("Parsing configuration of {}",
338 moduleLocalNameFromXPath);
339 yangToAttributes = fillConfiguration(choiceCaseNode,
340 currentModule, typeProviderWrapper,
341 qNamesToSIEs, schemaContext);
342 checkUniqueAttributesWithGeneratedClass(
343 uniqueGeneratedClassesNames, when.getQName(),
345 } else if (expectedStateAugmentationSchemaPath
346 .equals(augmentation.getTargetPath())) {
347 logger.debug("Parsing state of {}",
348 moduleLocalNameFromXPath);
350 runtimeBeans = fillRuntimeBeans(choiceCaseNode,
351 currentModule, typeProviderWrapper,
352 packageName, moduleLocalNameFromXPath,
354 } catch (NameConflictException e) {
355 throw new NameConflictException(
356 e.getConflictingName(), when.getQName(),
360 checkUniqueRuntimeBeansGeneratedClasses(
361 uniqueGeneratedClassesNames, when, runtimeBeans);
362 Set<RuntimeBeanEntry> runtimeBeanEntryValues = Sets
363 .newHashSet(runtimeBeans);
364 for (RuntimeBeanEntry entry : runtimeBeanEntryValues) {
365 checkUniqueAttributesWithGeneratedClass(
366 uniqueGeneratedClassesNames,
368 entry.getYangPropertiesToTypesMap());
372 throw new IllegalArgumentException(
373 "Cannot parse augmentation " + augmentation);
375 if (result.containsKey(moduleLocalNameFromXPath)) {
376 // either fill runtimeBeans or yangToAttributes
377 ModuleMXBeanEntry moduleMXBeanEntry = result
378 .get(moduleLocalNameFromXPath);
379 if (yangToAttributes != null
380 && moduleMXBeanEntry.getAttributes() == null) {
382 .setYangToAttributes(yangToAttributes);
383 } else if (runtimeBeans != null
384 && moduleMXBeanEntry.getRuntimeBeans() == null) {
385 moduleMXBeanEntry.setRuntimeBeans(runtimeBeans);
388 // construct ModuleMXBeanEntry
389 ModuleMXBeanEntry moduleMXBeanEntry = new ModuleMXBeanEntry(
390 moduleIdentity, yangToAttributes, packageName,
391 providedServices, javaNamePrefix, currentModule
392 .getNamespace().toString(),
394 moduleMXBeanEntry.setYangModuleName(currentModule
397 .setYangModuleLocalname(moduleLocalNameFromXPath);
398 result.put(moduleLocalNameFromXPath, moduleMXBeanEntry);
400 } // skip if child node is not ChoiceCaseNode
401 } // skip if childNodes != 1
404 for (Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
405 ModuleMXBeanEntry module = entry.getValue();
406 if (module.getAttributes() == null) {
407 module.setYangToAttributes(Collections
408 .<String, AttributeIfc> emptyMap());
409 } else if (module.getRuntimeBeans() == null) {
410 module.setRuntimeBeans(Collections
411 .<RuntimeBeanEntry> emptyList());
414 if (unaugmentedModuleIdentities.size() > 0) {
415 logger.warn("Augmentation not found for all module identities: {}",
416 unaugmentedModuleIdentities.keySet());
419 logger.debug("Number of ModuleMXBeans to be generated: {}",
424 private static void checkUniqueRuntimeBeansGeneratedClasses(
425 Map<String, QName> uniqueGeneratedClassesNames,
426 DataSchemaNode when, Collection<RuntimeBeanEntry> runtimeBeans) {
427 for (RuntimeBeanEntry runtimeBean : runtimeBeans) {
428 final String javaNameOfRuntimeMXBean = runtimeBean
429 .getJavaNameOfRuntimeMXBean();
430 if (uniqueGeneratedClassesNames
431 .containsKey(javaNameOfRuntimeMXBean)) {
432 QName firstDefinedQName = uniqueGeneratedClassesNames
433 .get(javaNameOfRuntimeMXBean);
434 throw new NameConflictException(javaNameOfRuntimeMXBean,
435 firstDefinedQName, when.getQName());
437 uniqueGeneratedClassesNames.put(javaNameOfRuntimeMXBean,
442 private static void checkUniqueAttributesWithGeneratedClass(
443 Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
444 Map<String, AttributeIfc> yangToAttributes) {
445 for (Entry<String, AttributeIfc> attr : yangToAttributes.entrySet()) {
446 if (attr.getValue() instanceof TOAttribute) {
447 checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName,
448 (TOAttribute) attr.getValue());
449 } else if (attr.getValue() instanceof ListAttribute
450 && ((ListAttribute) attr.getValue()).getInnerAttribute() instanceof TOAttribute) {
451 checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName,
452 (TOAttribute) ((ListAttribute) attr.getValue())
453 .getInnerAttribute());
458 private static void checkUniqueTOAttr(
459 Map<String, QName> uniqueGeneratedClassNames, QName parentQName,
461 final String upperCaseCammelCase = attr.getUpperCaseCammelCase();
462 if (uniqueGeneratedClassNames.containsKey(upperCaseCammelCase)) {
463 QName firstDefinedQName = uniqueGeneratedClassNames
464 .get(upperCaseCammelCase);
465 throw new NameConflictException(upperCaseCammelCase,
466 firstDefinedQName, parentQName);
468 uniqueGeneratedClassNames.put(upperCaseCammelCase, parentQName);
472 private static Collection<RuntimeBeanEntry> fillRuntimeBeans(
473 ChoiceCaseNode choiceCaseNode, Module currentModule,
474 TypeProviderWrapper typeProviderWrapper, String packageName,
475 String moduleLocalNameFromXPath, String javaNamePrefix) {
477 return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName,
478 choiceCaseNode, moduleLocalNameFromXPath, typeProviderWrapper,
479 javaNamePrefix, currentModule).values();
483 private static Map<String, AttributeIfc> fillConfiguration(
484 ChoiceCaseNode choiceCaseNode, Module currentModule,
485 TypeProviderWrapper typeProviderWrapper,
486 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
487 SchemaContext schemaContext) {
488 Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
489 for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) {
490 AttributeIfc attributeValue = getAttributeValue(attrNode,
491 currentModule, qNamesToSIEs, typeProviderWrapper,
493 yangToAttributes.put(attributeValue.getAttributeYangName(),
496 return yangToAttributes;
499 private static Map<String, QName> findProvidedServices(
500 IdentitySchemaNode moduleIdentity, Module currentModule,
501 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
502 SchemaContext schemaContext) {
503 Map<String, QName> result = new HashMap<>();
504 for (UnknownSchemaNode unknownNode : moduleIdentity
505 .getUnknownSchemaNodes()) {
506 if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME
507 .equals(unknownNode.getNodeType())) {
508 String prefixAndIdentityLocalName = unknownNode
510 ServiceInterfaceEntry sie = findSIE(prefixAndIdentityLocalName,
511 currentModule, qNamesToSIEs, schemaContext);
512 result.put(sie.getFullyQualifiedName(), sie.getQName());
519 * For input node, find if it contains config:java-name-prefix extension. If
520 * not found, convert local name of node converted to cammel case.
522 public static String findJavaNamePrefix(SchemaNode schemaNode) {
523 return convertToJavaName(schemaNode, true);
526 public static String findJavaParameter(SchemaNode schemaNode) {
527 return convertToJavaName(schemaNode, false);
530 public static String convertToJavaName(SchemaNode schemaNode,
531 boolean capitalizeFirstLetter) {
532 for (UnknownSchemaNode unknownNode : schemaNode.getUnknownSchemaNodes()) {
533 if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME
534 .equals(unknownNode.getNodeType())) {
535 String value = unknownNode.getNodeParameter();
536 return convertToJavaName(value, capitalizeFirstLetter);
539 return convertToJavaName(schemaNode.getQName().getLocalName(),
540 capitalizeFirstLetter);
543 public static String convertToJavaName(String localName,
544 boolean capitalizeFirstLetter) {
545 if (capitalizeFirstLetter) {
546 return BindingGeneratorUtil.parseToClassName(localName);
548 return BindingGeneratorUtil.parseToValidParamName(localName);
552 private static int getChildNodeSizeWithoutUses(ContainerSchemaNode csn) {
554 for (DataSchemaNode dsn : csn.getChildNodes()) {
555 if (dsn.isAddedByUses() == false)
561 private static AttributeIfc getAttributeValue(DataSchemaNode attrNode,
562 Module currentModule,
563 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
564 TypeProviderWrapper typeProviderWrapper, SchemaContext schemaContext) {
566 if (attrNode instanceof LeafSchemaNode) {
568 LeafSchemaNode leaf = (LeafSchemaNode) attrNode;
569 return new JavaAttribute(leaf, typeProviderWrapper);
570 } else if (attrNode instanceof ContainerSchemaNode) {
572 ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
573 if (containerSchemaNode.getUses().size() == 1
574 && getChildNodeSizeWithoutUses(containerSchemaNode) == 0) {
576 UsesNode usesNode = containerSchemaNode.getUses().iterator()
578 checkState(usesNode.getRefines().size() == 1,
579 "Unexpected 'refine' child node size of "
580 + containerSchemaNode);
581 LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines()
582 .values().iterator().next();
583 checkState(refine.getUnknownSchemaNodes().size() == 1,
584 "Unexpected unknown schema node size of " + refine);
585 UnknownSchemaNode requiredIdentity = refine
586 .getUnknownSchemaNodes().iterator().next();
588 ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity
590 "Unexpected language extension " + requiredIdentity);
591 String prefixAndIdentityLocalName = requiredIdentity
593 // import should point to a module
594 ServiceInterfaceEntry serviceInterfaceEntry = findSIE(
595 prefixAndIdentityLocalName, currentModule,
596 qNamesToSIEs, schemaContext);
597 boolean mandatory = refine.getConstraints().isMandatory();
598 return new DependencyAttribute(attrNode, serviceInterfaceEntry,
599 mandatory, attrNode.getDescription());
601 return TOAttribute.create(containerSchemaNode,
602 typeProviderWrapper);
604 } else if (attrNode instanceof LeafListSchemaNode) {
605 return ListAttribute.create((LeafListSchemaNode) attrNode,
606 typeProviderWrapper);
607 } else if (attrNode instanceof ListSchemaNode) {
608 return ListAttribute.create((ListSchemaNode) attrNode,
609 typeProviderWrapper);
611 throw new UnsupportedOperationException(
612 "Unknown configuration node " + attrNode.toString());
616 private static ServiceInterfaceEntry findSIE(
617 String prefixAndIdentityLocalName, Module currentModule,
618 Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
619 SchemaContext schemaContext) {
621 Matcher m = PREFIX_COLON_LOCAL_NAME.matcher(prefixAndIdentityLocalName);
625 // if there is a prefix, look for ModuleImport with this prefix. Get
626 // Module from SchemaContext
627 String prefix = m.group(1);
628 ModuleImport moduleImport = findModuleImport(currentModule, prefix);
629 foundModule = schemaContext.findModuleByName(
630 moduleImport.getModuleName(), moduleImport.getRevision());
633 format("Module not found in SchemaContext by %s",
635 localSIName = m.group(2);
637 foundModule = currentModule; // no prefix => SIE is in currentModule
638 localSIName = prefixAndIdentityLocalName;
640 QName siQName = new QName(foundModule.getNamespace(),
641 foundModule.getRevision(), localSIName);
642 ServiceInterfaceEntry sie = qNamesToSIEs.get(siQName);
643 checkState(sie != null, "Cannot find referenced Service Interface by "
644 + prefixAndIdentityLocalName);
648 private static ModuleImport findModuleImport(Module module, String prefix) {
649 for (ModuleImport moduleImport : module.getImports()) {
650 if (moduleImport.getPrefix().equals(prefix)) {
654 throw new IllegalStateException(format(
655 "Import not found with prefix %s in %s", prefix, module));
658 public Map<String, AttributeIfc> getAttributes() {
659 return yangToAttributes;
662 private void setYangToAttributes(Map<String, AttributeIfc> newAttributes) {
663 this.yangToAttributes = newAttributes;
667 public String getNullableDescription() {
668 return nullableDescription;
672 public String toString() {
673 return "ModuleMXBeanEntry{" + "globallyUniqueName='"
674 + globallyUniqueName + '\'' + ", packageName='" + packageName