subPackageNameForTypeDefinition);
// test of exception part of the method moduleNamespaceToPackageName()
- ModuleBuilder moduleBuilder = new ModuleBuilder("module-withut-revision");
+ ModuleBuilder moduleBuilder = new ModuleBuilder("module-withut-revision", null);
Module moduleWithoutRevision = moduleBuilder.build();
boolean passedSuccesfully = false;
try {
return null;
}
+ private File generateStringToJavaFile(final File parentDir, final String generatedCode, String packageName,
+ final CodeGenerator generator) throws IOException {
+ if (parentDir == null) {
+ LOG.warn("Parent Directory not specified, files will be generated "
+ + "accordingly to generated Type package path.");
+ }
+ if (generator == null) {
+ LOG.error("Cannot generate Type into Java File because " + "Code Generator instance is NULL!");
+ throw new IllegalArgumentException("Code Generator Cannot be NULL!");
+ }
+ final File packageDir = packageToDirectory(parentDir, packageName);
+
+ if (!packageDir.exists()) {
+ packageDir.mkdirs();
+ }
+
+ if (generatedCode.isEmpty()) {
+ throw new IllegalStateException("Generated code should not be empty!");
+ }
+ final File file = new File(packageDir, "YangModuleInfoImpl.java");
+ try (final OutputStream stream = buildContext.newFileOutputStream(file)) {
+ try (final Writer fw = new OutputStreamWriter(stream)) {
+ try (final BufferedWriter bw = new BufferedWriter(fw)) {
+ bw.write(generatedCode);
+ }
+ } catch (IOException e) {
+ LOG.error("Failed to write generate output into {}", file.getPath(), e);
+ throw e;
+ }
+ }
+ return file;
+ }
+
/**
* Creates the package directory path as concatenation of
* <code>parentDirectory</code> and parsed <code>packageName</code>. The
* @return <code>File</code> object which refers to the new directory for
* package <code>packageName</code>
*/
- private File packageToDirectory(final File parentDirectory, final String packageName) {
+ public static File packageToDirectory(final File parentDirectory, final String packageName) {
if (packageName == null) {
throw new IllegalArgumentException("Package Name cannot be NULL!");
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.java.api.generator
+
+import org.opendaylight.yangtools.yang.model.api.Module
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo
+import java.io.InputStream
+import com.google.common.collect.ImmutableSet
+import java.util.Map
+import java.util.LinkedHashMap
+import org.opendaylight.yangtools.binding.generator.util.Types
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+import org.opendaylight.yangtools.sal.binding.model.api.WildcardType
+import java.io.IOException
+import java.util.Set
+import java.util.HashSet
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import java.util.Date
+import java.util.TreeMap
+import java.text.DateFormat
+import java.text.SimpleDateFormat
+
+class YangModuleInfoTemplate {
+ val CLASS = "$YangModuleInfoImpl"
+
+ val Module module
+ val SchemaContext ctx
+ val Map<String, String> importMap = new LinkedHashMap()
+
+ new (Module module, SchemaContext ctx) {
+ if (module == null) {
+ throw new IllegalArgumentException("Module reference cannot be NULL!")
+ }
+ this.module = module
+ this.ctx = ctx
+ }
+
+ def String generate() {
+ val String classBody = body().toString
+ '''
+ package «BindingGeneratorUtil.moduleNamespaceToPackageName(module)» ;
+
+ «imports»
+
+ «classBody»
+ '''.toString
+ }
+
+ def body() '''
+ public class «CLASS» implements «YangModuleInfo.importedName» {
+
+ private static final «YangModuleInfo.importedName» INSTANCE = new «CLASS»();
+
+ private «CLASS»() {}
+
+ public static «YangModuleInfo.importedName» getInstance() {
+ return INSTANCE;
+ }
+
+ «module.classBody»
+
+ }
+ '''
+
+ private def CharSequence classBody(Module m) '''
+ @Override
+ public «String.importedName» getName() {
+ return "«m.name»";
+ }
+
+ @Override
+ public «String.importedName» getRevision() {
+ «val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
+ return "«df.format(m.revision)»";
+ }
+
+ @Override
+ public «String.importedName» getNamespace() {
+ return "«m.namespace.toString»";
+ }
+
+ @Override
+ public «InputStream.importedName» getModuleSourceStream() throws «IOException.importedName» {
+ «val path = m.moduleSourcePath»
+ «IF path == null»
+ return null;
+ «ELSE»
+ return «CLASS».class.getResourceAsStream("«path»");
+ «ENDIF»
+ }
+
+ @Override
+ public «ImmutableSet.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
+ «Set.importedName»<«YangModuleInfo.importedName»> set = new «HashSet.importedName»<>();
+ «FOR imp : m.imports»
+ «val name = imp.moduleName»
+ «val rev = imp.revision»
+ «IF rev == null»
+ «val Set<Module> modules = ctx.modules»
+ «val TreeMap<Date, Module> sorted = new TreeMap()»
+ «FOR module : modules»
+ «IF module.name.equals(name)»
+ «sorted.put(module.revision, module)»
+ «ENDIF»
+ «ENDFOR»
+ set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(sorted.lastEntry().value)».«CLASS».getInstance());
+ «ELSE»
+ set.add(«BindingGeneratorUtil.moduleNamespaceToPackageName(ctx.findModuleByName(name, rev))».«CLASS».getInstance());
+ «ENDIF»
+ «ENDFOR»
+ return «ImmutableSet.importedName».copyOf(set);
+ }
+ '''
+
+ private def imports() '''
+ «IF !importMap.empty»
+ «FOR entry : importMap.entrySet»
+ «IF entry.value != BindingGeneratorUtil.moduleNamespaceToPackageName(module)»
+ import «entry.value».«entry.key»;
+ «ENDIF»
+ «ENDFOR»
+ «ENDIF»
+
+ '''
+
+ final protected def importedName(Class<?> cls) {
+ val Type intype = Types.typeForClass(cls)
+ putTypeIntoImports(intype);
+ getExplicitType(intype)
+ }
+
+ final def void putTypeIntoImports(Type type) {
+ val String typeName = type.getName();
+ val String typePackageName = type.getPackageName();
+ if (typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
+ return;
+ }
+ if (!importMap.containsKey(typeName)) {
+ importMap.put(typeName, typePackageName);
+ }
+ if (type instanceof ParameterizedType) {
+ val ParameterizedType paramType = (type as ParameterizedType)
+ val Type[] params = paramType.getActualTypeArguments()
+ if (params != null) {
+ for (Type param : params) {
+ putTypeIntoImports(param);
+ }
+ }
+ }
+ }
+
+ final def String getExplicitType(Type type) {
+ val String typePackageName = type.getPackageName();
+ val String typeName = type.getName();
+ val String importedPackageName = importMap.get(typeName);
+ var StringBuilder builder;
+ if (typePackageName.equals(importedPackageName)) {
+ builder = new StringBuilder(type.getName());
+ addActualTypeParameters(builder, type);
+ if (builder.toString().equals("Void")) {
+ return "void";
+ }
+ } else {
+ builder = new StringBuilder();
+ if (typePackageName.startsWith("java.lang")) {
+ builder.append(type.getName());
+ } else {
+ if (!typePackageName.isEmpty()) {
+ builder.append(typePackageName + Constants.DOT + type.getName());
+ } else {
+ builder.append(type.getName());
+ }
+ }
+ if (type.equals(Types.voidType())) {
+ return "void";
+ }
+ addActualTypeParameters(builder, type);
+ }
+ return builder.toString();
+ }
+
+ final def StringBuilder addActualTypeParameters(StringBuilder builder, Type type) {
+ if (type instanceof ParameterizedType) {
+ val ParameterizedType pType = (type as ParameterizedType)
+ val Type[] pTypes = pType.getActualTypeArguments();
+ builder.append("<");
+ builder.append(getParameters(pTypes));
+ builder.append(">");
+ }
+ return builder;
+ }
+
+ final def String getParameters(Type[] pTypes) {
+ if (pTypes == null || pTypes.length == 0) {
+ return "?";
+ }
+ val StringBuilder builder = new StringBuilder();
+
+ var int i = 0;
+ for (pType : pTypes) {
+ val Type t = pTypes.get(i)
+
+ var String separator = ",";
+ if (i == (pTypes.length - 1)) {
+ separator = "";
+ }
+
+ var String wildcardParam = "";
+ if (t.equals(Types.voidType())) {
+ builder.append("java.lang.Void" + separator);
+ } else {
+
+ if (t instanceof WildcardType) {
+ wildcardParam = "? extends ";
+ }
+
+ builder.append(wildcardParam + getExplicitType(t) + separator);
+ i = i + 1
+ }
+ }
+ return builder.toString();
+ }
+
+}
*/
package org.opendaylight.yangtools.maven.sal.api.gen.plugin;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.sal.java.api.generator.YangModuleInfoTemplate;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang2sources.spi.BuildContextAware;
if (persistentSourcesDir == null) {
persistentSourcesDir = new File(projectBaseDir, "src" + FS + "main" + FS + "java");
}
- return generator.generateToFile(outputBaseDir, persistentSourcesDir);
+
+ List<File> result = generator.generateToFile(outputBaseDir, persistentSourcesDir);
+ for (Module module : yangModules) {
+ // TODO: add YangModuleInfo class
+ result.add(generateYangModuleInfo(outputBaseDir, module, context));
+ }
+ return result;
}
@Override
this.buildContext = Preconditions.checkNotNull(buildContext);
}
+ private File generateYangModuleInfo(File outputBaseDir, Module module, SchemaContext ctx) {
+ final YangModuleInfoTemplate template = new YangModuleInfoTemplate(module, ctx);
+ String generatedCode = template.generate();
+ if (generatedCode.isEmpty()) {
+ throw new IllegalStateException("Generated code should not be empty!");
+ }
+
+ final File packageDir = GeneratorJavaFile.packageToDirectory(outputBaseDir, BindingGeneratorUtil.moduleNamespaceToPackageName(module));
+
+ final File file = new File(packageDir, "$YangModuleInfoImpl.java");
+ try (final OutputStream stream = buildContext.newFileOutputStream(file)) {
+ try (final Writer fw = new OutputStreamWriter(stream)) {
+ try (final BufferedWriter bw = new BufferedWriter(fw)) {
+ bw.write(generatedCode);
+ }
+ } catch (Exception e) {
+ // TODO handle exception
+ }
+ } catch (Exception e) {
+ // TODO handle exception
+ }
+ return file;
+
+ }
+
}
/**
* Returns yang module name
- *
+ *
* @return
*/
String getName();
-
+
/**
- *
+ *
* Returns revision of yang module.
- *
+ *
* @return
*/
String getRevision();
-
+
/**
* Returns XML namespace associated to the YANG module
- *
+ *
* @return XML namespace associated to the YANG module.
*/
String getNamespace();
-
+
InputStream getModuleSourceStream() throws IOException;
-
+
ImmutableSet<YangModuleInfo> getImportedModules();
+
}
import java.io.Closeable;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import org.apache.maven.project.MavenProject;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
return result;
}
- static class NamedFileInputStream extends FileInputStream {
- private final File file;
-
- NamedFileInputStream(File file) throws FileNotFoundException {
- super(file);
- this.file = file;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "{" + file + "}";
- }
- }
-
private static void toCache(final File rootDir, final Collection<File> yangFiles) {
cache.put(rootDir, yangFiles);
}
}
});
for (File yangFile : yangFiles) {
- yangsFromDependencies.add(new NamedFileInputStream(yangFile));
+ yangsFromDependencies.add(new NamedFileInputStream(yangFile, YangToSourcesProcessor.META_INF_YANG_STRING + File.separator + yangFile.getName()));
}
}
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
import org.opendaylight.yangtools.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
import org.opendaylight.yangtools.yang2sources.plugin.Util.ContextHolder;
-import org.opendaylight.yangtools.yang2sources.plugin.Util.NamedFileInputStream;
import org.opendaylight.yangtools.yang2sources.plugin.Util.YangsInZipsResult;
import org.opendaylight.yangtools.yang2sources.spi.BuildContextAware;
import org.opendaylight.yangtools.yang2sources.spi.CodeGenerator;
log.info(Util.message("No input files found", LOG_PREFIX));
return null;
}
-
+
/*
* Check if any of the listed files changed. If no changes occurred,
* simply return null, which indicates and of execution.
final List<InputStream> yangsInProject = new ArrayList<>();
for (final File f : yangFilesInProject) {
- yangsInProject.add(new NamedFileInputStream(f));
+ yangsInProject.add(new NamedFileInputStream(f, META_INF_YANG_STRING + File.separator + f.getName()));
}
List<InputStream> all = new ArrayList<>(yangsInProject);
</code>
*/
-public interface Module extends DataNodeContainer, YangNode {
+public interface Module extends DataNodeContainer, YangNode, SourceStreamAware {
/**
* Returns the namespace of the module which is specified as argument of
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.model.api;
+
+public interface SourceStreamAware {
+
+ String getModuleSourcePath();
+
+}
private final ModuleImpl instance;
private final String name;
+ private final String sourcePath;
private final SchemaPath schemaPath;
private URI namespace;
private String prefix;
private final List<ListSchemaNodeBuilder> allLists = new ArrayList<ListSchemaNodeBuilder>();
- public ModuleBuilder(final String name) {
- this(name, false);
+ public ModuleBuilder(final String name, final String sourcePath) {
+ this(name, false, sourcePath);
}
- public ModuleBuilder(final String name, final boolean submodule) {
+ public ModuleBuilder(final String name, final boolean submodule, final String sourcePath) {
super(name, 0, null);
this.name = name;
+ this.sourcePath = sourcePath;
schemaPath = new SchemaPath(Collections.<QName> emptyList(), true);
- instance = new ModuleImpl(name);
this.submodule = submodule;
+ instance = new ModuleImpl(name, sourcePath);
actualPath.push(this);
}
public ModuleBuilder(Module base) {
super(base.getName(), 0, null);
this.name = base.getName();
+ this.sourcePath = base.getModuleSourcePath();
schemaPath = new SchemaPath(Collections.<QName> emptyList(), true);
- instance = new ModuleImpl(base.getName());
submodule = false;
+ instance = new ModuleImpl(base.getName(), base.getModuleSourcePath());
actualPath.push(this);
-
namespace = base.getNamespace();
prefix = base.getPrefix();
revision = base.getRevision();
return instance;
}
+ public String getModuleSourcePath() {
+ return sourcePath;
+ }
+
@Override
public void setParent(Builder parent) {
throw new YangParseException(name, 0, "Can not set parent to module");
private final class ModuleImpl implements Module {
private URI namespace;
private final String name;
+ private final String sourcePath;
private Date revision;
private String prefix;
private String yangVersion;
private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
private final List<UnknownSchemaNode> unknownNodes = new ArrayList<>();
- private ModuleImpl(String name) {
+ private ModuleImpl(String name, String sourcePath) {
this.name = name;
+ this.sourcePath = sourcePath;
+ }
+
+ @Override
+ public String getModuleSourcePath() {
+ return sourcePath;
}
@Override
import org.opendaylight.yangtools.yang.parser.util.GroupingSort;
import org.opendaylight.yangtools.yang.parser.util.GroupingUtils;
import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
+import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
import org.opendaylight.yangtools.yang.parser.util.ParserUtils;
import org.opendaylight.yangtools.yang.parser.util.YangParseException;
import org.opendaylight.yangtools.yang.validator.YangModelBasicValidator;
YangParserListenerImpl yangModelParser;
for (Map.Entry<InputStream, ParseTree> entry : trees.entrySet()) {
- yangModelParser = new YangParserListenerImpl();
+ InputStream is = entry.getKey();
+ String path = null;
+ if (is instanceof NamedFileInputStream) {
+ NamedFileInputStream nis = (NamedFileInputStream)is;
+ path = nis.getFileDestination();
+ }
+ yangModelParser = new YangParserListenerImpl(path);
walker.walk(yangModelParser, entry.getValue());
ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
private static final Logger LOGGER = LoggerFactory.getLogger(YangParserListenerImpl.class);
private static final String AUGMENT_STR = "augment";
+ private final String sourcePath;
private ModuleBuilder moduleBuilder;
private String moduleName;
private URI namespace;
return actualPath.peek().pop();
}
+ public YangParserListenerImpl(String sourcePath) {
+ this.sourcePath = sourcePath;
+ }
+
@Override
public void enterModule_stmt(YangParser.Module_stmtContext ctx) {
moduleName = stringFromNode(ctx);
enterLog("module", moduleName, 0);
actualPath.push(new Stack<QName>());
- moduleBuilder = new ModuleBuilder(moduleName);
+ moduleBuilder = new ModuleBuilder(moduleName, sourcePath);
String description = null;
String reference = null;
enterLog("submodule", moduleName, 0);
actualPath.push(new Stack<QName>());
- moduleBuilder = new ModuleBuilder(moduleName, true);
+ moduleBuilder = new ModuleBuilder(moduleName, true, sourcePath);
String description = null;
String reference = null;
for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
c.addUnknownNodeBuilder((copy(un, c, updateQName)));
}
+ c.setExtensionBuilder(old.getExtensionBuilder());
+ c.setExtensionDefinition(old.getExtensionDefinition());
return c;
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+public class NamedFileInputStream extends FileInputStream {
+ private final String fileDestination;
+
+ public NamedFileInputStream(File file, String fileDestination) throws FileNotFoundException {
+ super(file);
+ this.fileDestination = fileDestination;
+ }
+
+ public String getFileDestination() {
+ return fileDestination;
+ }
+
+}
/**
* Create java.util.List of key node names.
*
- * @param keyDefinition
- * key definition as string
+ * @param ctx
+ * Key_stmtContext context
* @return YANG list key as java.util.List of key node names
*/
public static List<String> createListKey(final Key_stmtContext ctx) {