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.base.Function;
12 import com.google.common.base.Optional;
13 import com.google.common.collect.Collections2;
14 import com.google.common.collect.Maps;
15 import com.google.common.collect.Sets;
16 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AbstractDependencyAttribute;
17 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
18 import org.opendaylight.controller.config.yangjmxgenerator.attribute.DependencyAttribute;
19 import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
20 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
21 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
22 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
23 import org.opendaylight.controller.config.yangjmxgenerator.plugin.util.NameConflictException;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
26 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
27 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
29 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
33 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.Module;
35 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
36 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
37 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
38 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
39 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
40 import org.opendaylight.yangtools.yang.model.api.UsesNode;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 import javax.annotation.Nullable;
45 import java.util.Arrays;
46 import java.util.Collection;
47 import java.util.Collections;
48 import java.util.HashMap;
51 import java.util.regex.Matcher;
52 import java.util.regex.Pattern;
54 import static com.google.common.base.Preconditions.checkState;
55 import static java.lang.String.format;
56 import static org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants.createConfigQName;
58 final class ModuleMXBeanEntryBuilder {
60 private Module currentModule;
61 private Map<QName, ServiceInterfaceEntry> qNamesToSIEs;
62 private SchemaContext schemaContext;
63 private TypeProviderWrapper typeProviderWrapper;
64 private String packageName;
66 public ModuleMXBeanEntryBuilder setModule(Module module) {
67 this.currentModule = module;
71 public ModuleMXBeanEntryBuilder setqNamesToSIEs(Map<QName, ServiceInterfaceEntry> qNamesToSIEs) {
72 this.qNamesToSIEs = qNamesToSIEs;
76 public ModuleMXBeanEntryBuilder setSchemaContext(SchemaContext schemaContext) {
77 this.schemaContext = schemaContext;
81 public ModuleMXBeanEntryBuilder setTypeProviderWrapper(TypeProviderWrapper typeProviderWrapper) {
82 this.typeProviderWrapper = typeProviderWrapper;
86 public ModuleMXBeanEntryBuilder setPackageName(String packageName) {
87 this.packageName = packageName;
91 private static final Logger logger = LoggerFactory
92 .getLogger(ModuleMXBeanEntryBuilder.class);
94 // TODO: the XPath should be parsed by code generator IMO
95 private static final String MAGIC_STRING = "MAGIC_STRING";
96 private static final String MODULE_CONDITION_XPATH_TEMPLATE = "^/MAGIC_STRING:modules/MAGIC_STRING:module/MAGIC_STRING:type\\s*=\\s*['\"](.+)['\"]$";
97 private static final SchemaPath expectedConfigurationAugmentationSchemaPath = new SchemaPath(
98 Arrays.asList(createConfigQName("modules"),
99 createConfigQName("module"),
100 createConfigQName("configuration")), true);
101 private static final SchemaPath expectedStateAugmentationSchemaPath = new SchemaPath(
102 Arrays.asList(createConfigQName("modules"),
103 createConfigQName("module"), createConfigQName("state")),
105 private static final Pattern PREFIX_COLON_LOCAL_NAME = Pattern
106 .compile("^(.+):(.+)$");
109 public Map<String, ModuleMXBeanEntry> build() {
110 logger.debug("Generating ModuleMXBeans of {} to package {}",
111 currentModule.getNamespace(), packageName);
113 String configModulePrefix;
115 configModulePrefix = getConfigModulePrefixFromImport(currentModule);
116 } catch (IllegalArgumentException e) {
117 // this currentModule does not import config currentModule
118 return Collections.emptyMap();
121 // get identities of base config:currentModule-type
122 Map<String, IdentitySchemaNode> moduleIdentities = getIdentityMap();
124 Map<String, QName> uniqueGeneratedClassesNames = new HashMap<>();
126 // each currentModule name should have an augmentation defined
127 Map<String, IdentitySchemaNode> unaugmentedModuleIdentities = new HashMap<>(
130 Map<String, ModuleMXBeanEntry> result = new HashMap<>();
132 for (AugmentationSchema augmentation : currentModule.getAugmentations()) {
133 Set<DataSchemaNode> childNodes = augmentation.getChildNodes();
134 if (areAllChildrenChoiceCaseNodes(childNodes)) {
135 for (ChoiceCaseNode childCase : castChildNodesToChoiceCases(childNodes)) {
136 // TODO refactor, extract to standalone builder class
137 processChoiceCaseNode(result, uniqueGeneratedClassesNames, configModulePrefix, moduleIdentities,
138 unaugmentedModuleIdentities, augmentation, childCase);
140 } // skip if child nodes are not all cases
143 cleanUpNulls(result);
144 // check attributes name uniqueness
145 checkAttributeNamesUniqueness(uniqueGeneratedClassesNames, result);
146 checkUnaugumentedIdentities(unaugmentedModuleIdentities);
148 logger.debug("Number of ModuleMXBeans to be generated: {}", result.size());
153 private static void cleanUpNulls(Map<String, ModuleMXBeanEntry> result) {
154 for (Map.Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
155 ModuleMXBeanEntry module = entry.getValue();
156 if (module.getAttributes() == null) {
157 module.setYangToAttributes(Collections
158 .<String, AttributeIfc> emptyMap());
159 } else if (module.getRuntimeBeans() == null) {
160 module.setRuntimeBeans(Collections
161 .<RuntimeBeanEntry> emptyList());
166 private static void checkUnaugumentedIdentities(Map<String, IdentitySchemaNode> unaugmentedModuleIdentities) {
167 if (unaugmentedModuleIdentities.size() > 0) {
168 logger.warn("Augmentation not found for all currentModule identities: {}",
169 unaugmentedModuleIdentities.keySet());
173 private static void checkAttributeNamesUniqueness(Map<String, QName> uniqueGeneratedClassesNames, Map<String, ModuleMXBeanEntry> result) {
174 for (Map.Entry<String, ModuleMXBeanEntry> entry : result.entrySet()) {
175 checkUniqueRuntimeBeanAttributesName(entry.getValue(),
176 uniqueGeneratedClassesNames);
180 private Map<String, IdentitySchemaNode> getIdentityMap() {
181 Map<String, IdentitySchemaNode> moduleIdentities = Maps.newHashMap();
183 for (IdentitySchemaNode id : currentModule.getIdentities()) {
184 if (id.getBaseIdentity() != null
185 && ConfigConstants.MODULE_TYPE_Q_NAME.equals(id.getBaseIdentity().getQName())) {
186 String identityLocalName = id.getQName().getLocalName();
187 if (moduleIdentities.containsKey(identityLocalName)) {
188 throw new IllegalStateException("Module name already defined in this currentModule: "
189 + identityLocalName);
191 moduleIdentities.put(identityLocalName, id);
192 logger.debug("Found identity {}", identityLocalName);
194 // validation check on unknown schema nodes
195 boolean providedServiceWasSet = false;
196 for (UnknownSchemaNode unknownNode : id.getUnknownSchemaNodes()) {
198 boolean unknownNodeIsProvidedServiceExtension = ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME.equals(unknownNode.getNodeType());
199 // true => no op: 0 or more provided identities are allowed
201 if (ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
204 providedServiceWasSet == false,
205 format("More than one language extension %s is not allowed here: %s",
206 ConfigConstants.JAVA_NAME_PREFIX_EXTENSION_QNAME, id));
207 providedServiceWasSet = true;
208 } else if (unknownNodeIsProvidedServiceExtension == false) {
209 throw new IllegalStateException("Unexpected language extension " + unknownNode.getNodeType());
215 return moduleIdentities;
218 private Collection<ChoiceCaseNode> castChildNodesToChoiceCases(Set<DataSchemaNode> childNodes) {
219 return Collections2.transform(childNodes, new Function<DataSchemaNode, ChoiceCaseNode>() {
222 public ChoiceCaseNode apply(@Nullable DataSchemaNode input) {
223 return (ChoiceCaseNode) input;
228 private boolean areAllChildrenChoiceCaseNodes(Set<DataSchemaNode> childNodes) {
229 for (DataSchemaNode childNode : childNodes) {
230 if (childNode instanceof ChoiceCaseNode == false)
236 private void processChoiceCaseNode(Map<String, ModuleMXBeanEntry> result,
237 Map<String, QName> uniqueGeneratedClassesNames, String configModulePrefix,
238 Map<String, IdentitySchemaNode> moduleIdentities,
239 Map<String, IdentitySchemaNode> unaugmentedModuleIdentities, AugmentationSchema augmentation,
240 DataSchemaNode when) {
242 ChoiceCaseNode choiceCaseNode = (ChoiceCaseNode) when;
243 if (choiceCaseNode.getConstraints() == null || choiceCaseNode.getConstraints().getWhenCondition() == null) {
246 RevisionAwareXPath xPath = choiceCaseNode.getConstraints().getWhenCondition();
247 Matcher matcher = getWhenConditionMatcher(configModulePrefix, xPath);
248 if (matcher.matches() == false) {
251 String moduleLocalNameFromXPath = matcher.group(1);
252 IdentitySchemaNode moduleIdentity = moduleIdentities.get(moduleLocalNameFromXPath);
253 unaugmentedModuleIdentities.remove(moduleLocalNameFromXPath);
254 checkState(moduleIdentity != null, "Cannot find identity " + moduleLocalNameFromXPath
255 + " matching augmentation " + augmentation);
256 Map<String, QName> providedServices = findProvidedServices(moduleIdentity, currentModule, qNamesToSIEs,
259 if (moduleIdentity == null) {
260 throw new IllegalStateException("Cannot find identity specified by augmentation xpath constraint: "
261 + moduleLocalNameFromXPath + " of " + augmentation);
263 String javaNamePrefix = TypeProviderWrapper.findJavaNamePrefix(moduleIdentity);
265 Map<String, AttributeIfc> yangToAttributes = null;
267 Collection<RuntimeBeanEntry> runtimeBeans = null;
269 if (expectedConfigurationAugmentationSchemaPath.equals(augmentation.getTargetPath())) {
270 logger.debug("Parsing configuration of {}", moduleLocalNameFromXPath);
271 yangToAttributes = fillConfiguration(choiceCaseNode, currentModule, typeProviderWrapper, qNamesToSIEs,
272 schemaContext, packageName);
273 checkUniqueAttributesWithGeneratedClass(uniqueGeneratedClassesNames, when.getQName(), yangToAttributes);
274 } else if (expectedStateAugmentationSchemaPath.equals(augmentation.getTargetPath())) {
275 logger.debug("Parsing state of {}", moduleLocalNameFromXPath);
277 runtimeBeans = fillRuntimeBeans(choiceCaseNode, currentModule, typeProviderWrapper, packageName,
278 moduleLocalNameFromXPath, javaNamePrefix);
279 } catch (NameConflictException e) {
280 throw new NameConflictException(e.getConflictingName(), when.getQName(), when.getQName());
282 checkUniqueRuntimeBeansGeneratedClasses(uniqueGeneratedClassesNames, when, runtimeBeans);
283 Set<RuntimeBeanEntry> runtimeBeanEntryValues = Sets.newHashSet(runtimeBeans);
284 for (RuntimeBeanEntry entry : runtimeBeanEntryValues) {
285 checkUniqueAttributesWithGeneratedClass(uniqueGeneratedClassesNames, when.getQName(),
286 entry.getYangPropertiesToTypesMap());
290 throw new IllegalArgumentException("Cannot parse augmentation " + augmentation);
292 if (result.containsKey(moduleLocalNameFromXPath)) {
293 // either fill runtimeBeans or yangToAttributes
294 ModuleMXBeanEntry moduleMXBeanEntry = result.get(moduleLocalNameFromXPath);
295 if (yangToAttributes != null && moduleMXBeanEntry.getAttributes() == null) {
296 moduleMXBeanEntry.setYangToAttributes(yangToAttributes);
297 } else if (runtimeBeans != null && moduleMXBeanEntry.getRuntimeBeans() == null) {
298 moduleMXBeanEntry.setRuntimeBeans(runtimeBeans);
301 ModuleMXBeanEntry.ModuleMXBeanEntryInitial initial = new ModuleMXBeanEntry.ModuleMXBeanEntryInitialBuilder()
302 .setIdSchemaNode(moduleIdentity).setPackageName(packageName).setJavaNamePrefix(javaNamePrefix)
303 .setNamespace(currentModule.getNamespace().toString()).setqName(ModuleUtil.getQName(currentModule))
306 // construct ModuleMXBeanEntry
307 ModuleMXBeanEntry moduleMXBeanEntry = new ModuleMXBeanEntry(initial, yangToAttributes, providedServices,
310 moduleMXBeanEntry.setYangModuleName(currentModule.getName());
311 moduleMXBeanEntry.setYangModuleLocalname(moduleLocalNameFromXPath);
312 result.put(moduleLocalNameFromXPath, moduleMXBeanEntry);
316 private void checkUniqueRuntimeBeansGeneratedClasses(Map<String, QName> uniqueGeneratedClassesNames,
317 DataSchemaNode when, Collection<RuntimeBeanEntry> runtimeBeans) {
318 for (RuntimeBeanEntry runtimeBean : runtimeBeans) {
319 final String javaNameOfRuntimeMXBean = runtimeBean.getJavaNameOfRuntimeMXBean();
320 if (uniqueGeneratedClassesNames.containsKey(javaNameOfRuntimeMXBean)) {
321 QName firstDefinedQName = uniqueGeneratedClassesNames.get(javaNameOfRuntimeMXBean);
322 throw new NameConflictException(javaNameOfRuntimeMXBean, firstDefinedQName, when.getQName());
324 uniqueGeneratedClassesNames.put(javaNameOfRuntimeMXBean, when.getQName());
328 private static void checkUniqueRuntimeBeanAttributesName(ModuleMXBeanEntry mxBeanEntry,
329 Map<String, QName> uniqueGeneratedClassesNames) {
330 for (RuntimeBeanEntry runtimeBeanEntry : mxBeanEntry.getRuntimeBeans()) {
331 for (String runtimeAttName : runtimeBeanEntry.getYangPropertiesToTypesMap().keySet()) {
332 if (mxBeanEntry.getAttributes().keySet().contains(runtimeAttName)) {
333 QName qName1 = uniqueGeneratedClassesNames.get(runtimeBeanEntry.getJavaNameOfRuntimeMXBean());
334 QName qName2 = uniqueGeneratedClassesNames.get(mxBeanEntry.getGloballyUniqueName());
335 throw new NameConflictException(runtimeAttName, qName1, qName2);
341 private void checkUniqueAttributesWithGeneratedClass(Map<String, QName> uniqueGeneratedClassNames,
342 QName parentQName, Map<String, AttributeIfc> yangToAttributes) {
343 for (Map.Entry<String, AttributeIfc> attr : yangToAttributes.entrySet()) {
344 if (attr.getValue() instanceof TOAttribute) {
345 checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName, (TOAttribute) attr.getValue());
346 } else if (attr.getValue() instanceof ListAttribute
347 && ((ListAttribute) attr.getValue()).getInnerAttribute() instanceof TOAttribute) {
348 checkUniqueTOAttr(uniqueGeneratedClassNames, parentQName,
349 (TOAttribute) ((ListAttribute) attr.getValue()).getInnerAttribute());
354 private void checkUniqueTOAttr(Map<String, QName> uniqueGeneratedClassNames, QName parentQName, TOAttribute attr) {
355 final String upperCaseCammelCase = attr.getUpperCaseCammelCase();
356 if (uniqueGeneratedClassNames.containsKey(upperCaseCammelCase)) {
357 QName firstDefinedQName = uniqueGeneratedClassNames.get(upperCaseCammelCase);
358 throw new NameConflictException(upperCaseCammelCase, firstDefinedQName, parentQName);
360 uniqueGeneratedClassNames.put(upperCaseCammelCase, parentQName);
364 private Collection<RuntimeBeanEntry> fillRuntimeBeans(ChoiceCaseNode choiceCaseNode, Module currentModule,
365 TypeProviderWrapper typeProviderWrapper, String packageName, String moduleLocalNameFromXPath,
366 String javaNamePrefix) {
368 return RuntimeBeanEntry.extractClassNameToRuntimeBeanMap(packageName, choiceCaseNode, moduleLocalNameFromXPath,
369 typeProviderWrapper, javaNamePrefix, currentModule).values();
373 private Map<String, AttributeIfc> fillConfiguration(ChoiceCaseNode choiceCaseNode, Module currentModule,
374 TypeProviderWrapper typeProviderWrapper, Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
375 SchemaContext schemaContext, String packageName) {
376 Map<String, AttributeIfc> yangToAttributes = new HashMap<>();
377 for (DataSchemaNode attrNode : choiceCaseNode.getChildNodes()) {
378 AttributeIfc attributeValue = getAttributeValue(attrNode, currentModule, qNamesToSIEs, typeProviderWrapper,
379 schemaContext, packageName);
380 yangToAttributes.put(attributeValue.getAttributeYangName(), attributeValue);
382 return yangToAttributes;
385 private Map<String, QName> findProvidedServices(IdentitySchemaNode moduleIdentity, Module currentModule,
386 Map<QName, ServiceInterfaceEntry> qNamesToSIEs, SchemaContext schemaContext) {
387 Map<String, QName> result = new HashMap<>();
388 for (UnknownSchemaNode unknownNode : moduleIdentity.getUnknownSchemaNodes()) {
389 if (ConfigConstants.PROVIDED_SERVICE_EXTENSION_QNAME.equals(unknownNode.getNodeType())) {
390 String prefixAndIdentityLocalName = unknownNode.getNodeParameter();
391 ServiceInterfaceEntry sie = findSIE(prefixAndIdentityLocalName, currentModule, qNamesToSIEs,
393 result.put(sie.getFullyQualifiedName(), sie.getQName());
399 private AttributeIfc getAttributeValue(DataSchemaNode attrNode, Module currentModule,
400 Map<QName, ServiceInterfaceEntry> qNamesToSIEs, TypeProviderWrapper typeProviderWrapper,
401 SchemaContext schemaContext, String packageName) {
403 if (attrNode instanceof LeafSchemaNode) {
405 LeafSchemaNode leaf = (LeafSchemaNode) attrNode;
406 return new JavaAttribute(leaf, typeProviderWrapper);
407 } else if (attrNode instanceof ContainerSchemaNode) {
409 ContainerSchemaNode containerSchemaNode = (ContainerSchemaNode) attrNode;
410 Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
411 containerSchemaNode, attrNode, currentModule, qNamesToSIEs, schemaContext);
412 if (dependencyAttributeOptional.isPresent()) {
413 return dependencyAttributeOptional.get();
415 return TOAttribute.create(containerSchemaNode, typeProviderWrapper, packageName);
418 } else if (attrNode instanceof LeafListSchemaNode) {
419 return ListAttribute.create((LeafListSchemaNode) attrNode, typeProviderWrapper);
420 } else if (attrNode instanceof ListSchemaNode) {
421 ListSchemaNode listSchemaNode = (ListSchemaNode) attrNode;
422 Optional<? extends AbstractDependencyAttribute> dependencyAttributeOptional = extractDependency(
423 listSchemaNode, attrNode, currentModule, qNamesToSIEs, schemaContext);
424 if (dependencyAttributeOptional.isPresent()) {
425 return dependencyAttributeOptional.get();
427 return ListAttribute.create(listSchemaNode, typeProviderWrapper, packageName);
430 throw new UnsupportedOperationException("Unknown configuration node " + attrNode.toString());
434 private Optional<? extends AbstractDependencyAttribute> extractDependency(DataNodeContainer dataNodeContainer,
435 DataSchemaNode attrNode, Module currentModule, Map<QName, ServiceInterfaceEntry> qNamesToSIEs,
436 SchemaContext schemaContext) {
437 if (dataNodeContainer.getUses().size() == 1 && getChildNodeSizeWithoutUses(dataNodeContainer) == 0) {
439 UsesNode usesNode = dataNodeContainer.getUses().iterator().next();
440 checkState(usesNode.getRefines().size() == 1, "Unexpected 'refine' child node size of " + dataNodeContainer);
441 LeafSchemaNode refine = (LeafSchemaNode) usesNode.getRefines().values().iterator().next();
442 checkState(refine.getUnknownSchemaNodes().size() == 1, "Unexpected unknown schema node size of " + refine);
443 UnknownSchemaNode requiredIdentity = refine.getUnknownSchemaNodes().iterator().next();
444 checkState(ConfigConstants.REQUIRED_IDENTITY_EXTENSION_QNAME.equals(requiredIdentity.getNodeType()),
445 "Unexpected language extension " + requiredIdentity);
446 String prefixAndIdentityLocalName = requiredIdentity.getNodeParameter();
447 // import should point to a module
448 ServiceInterfaceEntry serviceInterfaceEntry = findSIE(prefixAndIdentityLocalName, currentModule,
449 qNamesToSIEs, schemaContext);
450 boolean mandatory = refine.getConstraints().isMandatory();
451 AbstractDependencyAttribute reference;
452 if (dataNodeContainer instanceof ContainerSchemaNode) {
453 reference = new DependencyAttribute(attrNode, serviceInterfaceEntry, mandatory,
454 attrNode.getDescription());
456 reference = new ListDependenciesAttribute(attrNode, serviceInterfaceEntry, mandatory,
457 attrNode.getDescription());
459 return Optional.of(reference);
461 return Optional.absent();
464 private int getChildNodeSizeWithoutUses(DataNodeContainer csn) {
466 for (DataSchemaNode dsn : csn.getChildNodes()) {
467 if (dsn.isAddedByUses() == false) {
474 private ServiceInterfaceEntry findSIE(String prefixAndIdentityLocalName, Module currentModule,
475 Map<QName, ServiceInterfaceEntry> qNamesToSIEs, SchemaContext schemaContext) {
477 Matcher m = PREFIX_COLON_LOCAL_NAME.matcher(prefixAndIdentityLocalName);
481 // if there is a prefix, look for ModuleImport with this prefix. Get
482 // Module from SchemaContext
483 String prefix = m.group(1);
484 ModuleImport moduleImport = findModuleImport(currentModule, prefix);
485 foundModule = schemaContext.findModuleByName(moduleImport.getModuleName(), moduleImport.getRevision());
486 checkState(foundModule != null, format("Module not found in SchemaContext by %s", moduleImport));
487 localSIName = m.group(2);
489 foundModule = currentModule; // no prefix => SIE is in currentModule
490 localSIName = prefixAndIdentityLocalName;
492 QName siQName = new QName(foundModule.getNamespace(), foundModule.getRevision(), localSIName);
493 ServiceInterfaceEntry sie = qNamesToSIEs.get(siQName);
494 checkState(sie != null, "Cannot find referenced Service Interface by " + prefixAndIdentityLocalName);
498 private ModuleImport findModuleImport(Module module, String prefix) {
499 for (ModuleImport moduleImport : module.getImports()) {
500 if (moduleImport.getPrefix().equals(prefix)) {
504 throw new IllegalStateException(format("Import not found with prefix %s in %s", prefix, module));
508 static Matcher getWhenConditionMatcher(String prefix, RevisionAwareXPath whenConstraint) {
509 String xpathRegex = MODULE_CONDITION_XPATH_TEMPLATE.replace(MAGIC_STRING, prefix);
510 Pattern pattern = Pattern.compile(xpathRegex);
511 return pattern.matcher(whenConstraint.toString());
514 String getConfigModulePrefixFromImport(Module currentModule) {
515 for (ModuleImport currentImport : currentModule.getImports()) {
516 if (currentImport.getModuleName().equals(ConfigConstants.CONFIG_MODULE)) {
517 return currentImport.getPrefix();
520 throw new IllegalArgumentException("Cannot find import " + ConfigConstants.CONFIG_MODULE + " in "