import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
+
+import com.google.common.base.Optional;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
return null;
}
- boolean fromUses = ((DataSchemaNode) result).isAddedByUses();
- final Iterator<UsesNode> groupingUses = grouping.getUses().iterator();
- while (groupingUses.hasNext() && fromUses) {
- result = findOriginalTargetFromGrouping(targetPath, groupingUses.next());
- if (result != null) {
- fromUses = ((DataSchemaNode) result).isAddedByUses();
+ if (result instanceof DerivableSchemaNode) {
+ DerivableSchemaNode castedResult = (DerivableSchemaNode) result;
+ Optional<? extends SchemaNode> originalNode = castedResult
+ .getOriginal();
+ if (castedResult.isAddedByUses() && originalNode.isPresent()) {
+ result = originalNode.get();
}
}
- if (fromUses) {
- // this indicates invalid yang and thus possible bug in code because
- // invalid yang should be already spotted by parser
- throw new IllegalStateException("Failed to generate code for augment in " + parentUsesNode);
- }
- return (DataSchemaNode) result;
+ if (result instanceof DataSchemaNode) {
+ DataSchemaNode resultDataSchemaNode = (DataSchemaNode) result;
+ if (resultDataSchemaNode.isAddedByUses()) {
+ // The original node is required, but we have only the copy of
+ // the original node.
+ // Maybe this indicates a bug in Yang parser.
+ throw new IllegalStateException(
+ "Failed to generate code for augment in "
+ + parentUsesNode);
+ } else {
+ return resultDataSchemaNode;
+ }
+ } else {
+ throw new IllegalStateException(
+ "Target node of uses-augment statement must be DataSchemaNode. Failed to generate code for augment in "
+ + parentUsesNode);
+ }
}
/**
--- /dev/null
+package org.opendaylight.yangtools.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import java.io.IOException;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import java.net.URISyntaxException;
+import java.io.File;
+import java.util.List;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.junit.Test;
+
+public class Bug4145Test {
+ @Test
+ public void bug4145Test() throws URISyntaxException, IOException, YangSyntaxErrorException {
+ File resourceFile = new File(getClass().getResource(
+ "/bug-4145/foo.yang").toURI());
+ File resourceDir = resourceFile.getParentFile();
+
+ YangParserImpl parser = YangParserImpl.getInstance();
+ SchemaContext context = parser.parseFile(resourceFile, resourceDir);
+
+ List<Type> generateTypes = new BindingGeneratorImpl(false)
+ .generateTypes(context);
+ assertNotNull(generateTypes);
+ assertTrue(generateTypes.size() > 0);
+ }
+}
return BindingMapping.getRootPackageName(module.getQNameModule());
}
+ /**
+ * Creates package name from specified <code>basePackageName</code> (package
+ * name for module) and <code>schemaPath</code>.
+ *
+ * Resulting package name is concatenation of <code>basePackageName</code>
+ * and all local names of YANG nodes which are parents of some node for
+ * which <code>schemaPath</code> is specified.
+ *
+ * @param basePackageName
+ * string with package name of the module, MUST be normalized,
+ * otherwise this method may return an invalid string.
+ * @param schemaPath
+ * list of names of YANG nodes which are parents of some node +
+ * name of this node
+ * @return string with valid JAVA package name
+ * @throws NullPointerException if any of the arguments are null
+ */
public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
- return packageNameForGeneratedType(basePackageName, schemaPath, false);
+ final int size = Iterables.size(schemaPath.getPathTowardsRoot()) - 1;
+ if (size <= 0) {
+ return basePackageName;
+ }
+
+ return generateNormalizedPackageName(basePackageName, schemaPath.getPathFromRoot(), size);
+ }
+
+ /**
+ * Creates package name from specified <code>basePackageName</code> (package
+ * name for module) and <code>schemaPath</code> which crosses an augmentation.
+ *
+ * Resulting package name is concatenation of <code>basePackageName</code>
+ * and all local names of YANG nodes which are parents of some node for
+ * which <code>schemaPath</code> is specified.
+ *
+ * @param basePackageName
+ * string with package name of the module, MUST be normalized,
+ * otherwise this method may return an invalid string.
+ * @param schemaPath
+ * list of names of YANG nodes which are parents of some node +
+ * name of this node
+ * @return string with valid JAVA package name
+ * @throws NullPointerException if any of the arguments are null
+ */
+ public static String packageNameForAugmentedGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
+ final int size = Iterables.size(schemaPath.getPathTowardsRoot());
+ if (size == 0) {
+ return basePackageName;
+ }
+
+ return generateNormalizedPackageName(basePackageName, schemaPath.getPathFromRoot(), size);
+ }
+
+ private static String generateNormalizedPackageName(final String base, final Iterable<QName> path, final int size) {
+ final StringBuilder builder = new StringBuilder(base);
+ final Iterator<QName> iterator = path.iterator();
+ for (int i = 0; i < size; ++i) {
+ builder.append('.');
+ String nodeLocalName = iterator.next().getLocalName();
+ // FIXME: Collon ":" is invalid in node local name as per RFC6020, identifier statement.
+ builder.append(DASH_COLON_MATCHER.replaceFrom(nodeLocalName, '.'));
+ }
+ return BindingMapping.normalizePackageName(builder.toString());
}
/**
* list of names of YANG nodes which are parents of some node +
* name of this node
* @return string with valid JAVA package name
+ *
+ * @deprecated Use {@link #packageNameForGeneratedType(String, SchemaPath)} or
+ * {@link #packageNameForAugmentedGeneratedType(String, SchemaPath)} instead.
*/
+ @Deprecated
public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath,
final boolean isUsesAugment) {
if (basePackageName == null) {
throw new IllegalArgumentException("Schema Path cannot be NULL!");
}
- final StringBuilder builder = new StringBuilder();
- builder.append(basePackageName);
final Iterable<QName> iterable = schemaPath.getPathFromRoot();
- final Iterator<QName> iterator = iterable.iterator();
- int size = Iterables.size(iterable);
+ final int size = Iterables.size(iterable);
final int traversalSteps;
if (isUsesAugment) {
traversalSteps = size;
} else {
traversalSteps = size - 1;
}
- for (int i = 0; i < traversalSteps; ++i) {
- builder.append('.');
- String nodeLocalName = iterator.next().getLocalName();
- // FIXME: Collon ":" is invalid in node local name as per RFC6020, identifier statement.
- builder.append(DASH_COLON_MATCHER.replaceFrom(nodeLocalName, '.'));
+
+ if (traversalSteps == 0) {
+ return BindingMapping.normalizePackageName(basePackageName);
}
- return BindingMapping.normalizePackageName(builder.toString());
+
+ return generateNormalizedPackageName(basePackageName, iterable, traversalSteps);
}
/**
* <li>if <code>basePackageName</code> equals <code>null</code></li>
* <li>if <code>typeDefinition</code> equals <code>null</code></li>
* </ul>
+ * @deprecated This method ignores typeDefinition argument and its result is only
+ * <code>indingMapping.normalizePackageName(basePackageName)</code>.
+ * Aside from tests, there is not a single user in OpenDaylight codebase,
+ * hence it can be considered buggy and defunct. It is scheduled for removal
+ * in Boron release.
*/
+ @Deprecated
public static String packageNameForTypeDefinition(final String basePackageName,
final TypeDefinition<?> typeDefinition) {
if (basePackageName == null) {
throw new IllegalArgumentException("Type Definition reference cannot be NULL!");
}
- final StringBuilder builder = new StringBuilder();
- builder.append(basePackageName);
- return BindingMapping.normalizePackageName(builder.toString());
+ return BindingMapping.normalizePackageName(basePackageName);
}
/**
* <li>if <code>token</code> equals null</li>
* </ul>
*/
-
private static String parseToCamelCase(final String token, final boolean uppercase) {
if (token == null) {
throw new IllegalArgumentException("Name can not be null");
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-
import com.google.common.base.Optional;
import java.io.File;
import java.io.IOException;
@Rule
public ExpectedException expectedEx = ExpectedException.none();
- private static List<File> loadTestResources(String testFile) {
+ private static List<File> loadTestResources(final String testFile) {
final List<File> testModels = new ArrayList<File>();
File listModelFile;
try {
* </ul>
*/
@Test
+ @Deprecated
public void testPackageNameForTypeDefinitionNullBasePackageName() {
expectedEx.expect(IllegalArgumentException.class);
expectedEx.expectMessage("Base Package Name cannot be NULL!");
* </ul>
*/
@Test
+ @Deprecated
public void testPackageNameForTypeDefinitionNullTypeDefinition() {
expectedEx.expect(IllegalArgumentException.class);
expectedEx.expectMessage("Type Definition reference cannot be NULL!");
*/
@Test
public void testPackageNameForGeneratedTypeNullBasePackageName() {
- expectedEx.expect(IllegalArgumentException.class);
- expectedEx.expectMessage("Base Package Name cannot be NULL!");
+ expectedEx.expect(NullPointerException.class);
BindingGeneratorUtil.packageNameForGeneratedType(null, null);
}
*/
@Test
public void testPackageNameForGeneratedTypeNullSchemaPath() {
- expectedEx.expect(IllegalArgumentException.class);
- expectedEx.expectMessage("Schema Path cannot be NULL!");
+ expectedEx.expect(NullPointerException.class);
BindingGeneratorUtil.packageNameForGeneratedType("test.package", null);
}