Commit 0271bff4 authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ progress with yang translator, generates output, open issues (WIP)

+ updated manifest
parent 5bf6de85
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -6,6 +6,9 @@ Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: European Telecommunications Standards Institute (ETSI)
Export-Package: org.etsi.mts.tdl.yang2tdl
Require-Bundle: org.etsi.mts.tdl.common,
 org.eclipse.emf.ecore,
 org.eclipse.xtext,
 org.etsi.mts.tdl.helper,
 org.etsi.mts.tdl.yang.tools.wrapper,
 org.eclipse.ui;resolution:=optional,
 org.eclipse.core.resources;resolution:=optional,
+187 −15
Original line number Diff line number Diff line
@@ -8,11 +8,22 @@ import java.util.Collection;
import java.util.Optional;
import java.util.Set;

import org.etsi.mts.tdl.CollectionDataType;
import org.etsi.mts.tdl.DataType;
import org.etsi.mts.tdl.Extension;
import org.etsi.mts.tdl.Member;
import org.etsi.mts.tdl.SimpleDataType;
import org.etsi.mts.tdl.StructuredDataType;
import org.etsi.mts.tdl.tdlFactory;
import org.etsi.mts.tdl.tdlPackage;
import org.etsi.mts.tdl.transform.AbstractTranslator;
import org.opendaylight.yangtools.odlext.parser.MountStatementSupport;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerLike;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -23,8 +34,11 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.LeafStatement;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.EmptyChoiceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.EmptyLeafEffectiveStatement;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.EmptyLeafListEffectiveStatement;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.RegularLeafEffectiveStatement;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.SlimLeafListEffectiveStatement;
import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredEffectiveStatement.Default;
import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException;
@@ -35,34 +49,177 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
import org.opendaylight.yangtools.yang.parser.stmt.reactor.ReactorDeclaredModel;

public class Yang2TDLTranslator extends AbstractTranslator {

    //inherited entry point
	@Override
	public void translate(String targetFilename) throws Exception {
		String sourceMappingTag = "SOURCE_MAPPING";
		drm = getTypeFor(sourceMappingTag, tdlPackage.Literals.DATA_RESOURCE_MAPPING);
		drm.setResourceURI(new File(targetFilename).getName());
		
		//TODO: resolve files
		//TODO: extract
        CrossSourceStatementReactor reactor = createReactor();
		BuildAction build = reactor.newBuild();
		Files.list(Path.of("samples", "ietf")).forEach(p -> 
			build.addLibSource(moduleFromPath(p.toString()))
		);
//		Files.list(Path.of("samples", "nfv")).forEach(p -> 
//			build.addSource(moduleFromPath(p.toString()))
//		);
		Files.list(Path.of("samples", "simple")).forEach(p -> 
			build.addSource(moduleFromPath(p.toString()))
		);
		SchemaContext schemaContext = build.buildEffective();
		//TODO: handle multimodule paths?
		//TODO: include meta-data
		//TODO: library of built-in types
		//TODO: add extensions
		translate(schemaContext);
	}


	private void translate(SchemaContext schemaContext) {
		for (DataSchemaNode c : schemaContext.getChildNodes()) {
			translate(c);
		}
		for (GroupingDefinition g : schemaContext.getGroupings()) {
			//TODO: filter only direct descendants? works with lib, but what if imports?
			//TODO: this should actually be a type that is then extended!!! (or inlined?)
			//	-> the problem with conflicting types remains..
			//  -> can refinement change also types? in that case it may make sense to inline/change super type?
			org.etsi.mts.tdl.Package p = tdlFactory.eINSTANCE.createPackage();
			p.setName("generated_from_"+g.getQName().getLocalName());
			getGeneratedPackage().getNestedPackage().add(p);
			org.etsi.mts.tdl.Package t = getGeneratedPackage();
			setGeneratedPackage(p);
			for (DataSchemaNode c : g.getChildNodes()) {
				translate(c);
			}
			setGeneratedPackage(t);
		}
	}


	private DataType translate(DataSchemaNode c) {
		String name = cleanName(c.getQName().getLocalName());
		if (c instanceof ContainerSchemaNode) {
			//create structured data type
			System.out.println("!c "+c.getQName().getLocalName() + " : " );
			StructuredDataType dataType = getStructuredDataTypeFor(name);
			for (DataSchemaNode child : ((ContainerSchemaNode) c).getChildNodes()) {
				DataType memberType = translate(child);
				String propertyName = child.getQName().getLocalName();
				Member m = getContentWithName((String) propertyName, dataType, tdlPackage.Literals.MEMBER);
				m.setDataType(memberType);
				if (m.container() == null) {
					dataType.getMember().add(m);
				}
			}
			return dataType;
		} else if (c instanceof ListSchemaNode) {
			//TODO: add key annotation?
			System.out.println("!l "+c.getQName().getLocalName() + " : " );
			StructuredDataType itemType = getStructuredDataTypeFor(name);
			CollectionDataType collectionType = getTypeFor(itemType.getName() + "_collection",
					tdlPackage.Literals.COLLECTION_DATA_TYPE);
			collectionType.setItemType(itemType);
			for (DataSchemaNode child : ((ListSchemaNode) c).getChildNodes()) {
				DataType memberType = translate(child);
				String propertyName = child.getQName().getLocalName();
				Member m = getContentWithName((String) propertyName, itemType, tdlPackage.Literals.MEMBER);
				m.setDataType(memberType);
				if (m.container() == null) {
					itemType.getMember().add(m);
				}
			}
			return collectionType;
			//create collection of structured data type
		} else if (c instanceof EmptyLeafListEffectiveStatement) {
			//TODO: unify and reuse
			System.out.println("!el "+c.getQName().getLocalName() + " : " );
			String typeName = ((EmptyLeafListEffectiveStatement) c).getType().getQName().getLocalName();
			SimpleDataType itemType = getSimpleDataTypeFor(typeName);
			CollectionDataType collectionType = getTypeFor(itemType.getName() + "_collection",
					tdlPackage.Literals.COLLECTION_DATA_TYPE);
			collectionType.setItemType(itemType);
			return collectionType;
		} else if (c instanceof SlimLeafListEffectiveStatement) {
			System.out.println("!sl "+c.getQName().getLocalName() + " : " );
//			DataType itemType = findElementOfType(name, tdlPackage.Literals.COLLECTION_DATA_TYPE);
//			if (itemType == null) {
//				itemType = getStructuredDataTypeFor(name);
//			}
			SimpleDataType itemType = getSimpleDataTypeFor("TODO");
			CollectionDataType collectionType = getTypeFor(itemType.getName() + "_collection",
					tdlPackage.Literals.COLLECTION_DATA_TYPE);
			collectionType.setItemType(itemType);
			return collectionType;
		} else if (c instanceof EmptyLeafEffectiveStatement) {
			System.out.println("!e "+c.getQName().getLocalName() + " : " + ((EmptyLeafEffectiveStatement) c).getType().getQName());
			String typeName = ((EmptyLeafEffectiveStatement) c).getType().getQName().getLocalName();
			SimpleDataType dataType = getSimpleDataTypeFor(typeName);
			TypeDefinition<?> baseType = ((EmptyLeafEffectiveStatement)c).getType().getBaseType();
			//TODO: what if extension is already present?
			if (baseType != null) {
				//TODO: handle enumeration -> add instances rather than extension
				SimpleDataType superType = getSimpleDataTypeFor(baseType.getQName().getLocalName());
				Extension e = tdlFactory.eINSTANCE.createExtension();
				e.setExtending(superType);
				dataType.setExtension(e);
			}
			//TODO: add constraints?
			return dataType;
		} else if (c instanceof RegularLeafEffectiveStatement) {
			//TODO: what is the difference
			System.out.println("!r "+c.getQName().getLocalName() + " : " + ((RegularLeafEffectiveStatement) c).getDeclared().getType().argument());
			String typeName = ((RegularLeafEffectiveStatement) c).getType().getQName().getLocalName();
			SimpleDataType dataType = getSimpleDataTypeFor(typeName);
			return dataType;
		} else if (c instanceof EmptyChoiceEffectiveStatement) {
			System.out.println("!cc "+c.getQName().getLocalName() + " : " + ((EmptyChoiceEffectiveStatement) c));
			//TODO: add annotation choice
			//TODO: need to skip cases?
			StructuredDataType dataType = getStructuredDataTypeFor(name);
			for (CaseSchemaNode child : ((EmptyChoiceEffectiveStatement) c).getCases()) {
				DataType memberType = translate(child);
				String propertyName = child.getQName().getLocalName();
				Member m = getContentWithName((String) propertyName, dataType, tdlPackage.Literals.MEMBER);
				m.setDataType(memberType);
				if (m.container() == null) {
					dataType.getMember().add(m);
				}
			}
			return dataType;
		} else {
			System.out.println(c);
			SimpleDataType todoType = getSimpleDataTypeFor("TODO");
			return todoType;
		}
	}
	
public class Yang2TDLTranslator {
	
	public static void main(String[] args) throws Exception {
        CrossSourceStatementReactor reactor = RFC7950Reactors.vanillaReactorBuilder()
        .addStatementSupport(ModelProcessingPhase.FULL_DECLARATION,
            new MountStatementSupport(YangParserConfiguration.DEFAULT))
        .build();
        CrossSourceStatementReactor reactor = createReactor();

//        processStatic(reactor);

		BuildAction build = reactor.newBuild();
		Files.list(Path.of("samples", "ietf")).forEach(p -> 
//			System.out.println("  "+p.toAbsolutePath())
//	//		System.out.println("  "+p.toString())
			build.addSource(moduleFromPath(p.toString()))
		);
//
//		Files.list(Path.of("samples", "simple")).forEach(p -> 
////			System.out.println("  "+p.toAbsolutePath())
////			System.out.println("  "+p.toString())
//			build.addSource(moduleFromResources(p.toString()))
//		Files.list(Path.of("samples", "nfv")).forEach(p -> 
//			build.addSource(moduleFromPath(p.toString()))
//		);
		Files.list(Path.of("samples", "nfv")).forEach(p -> 
////			System.out.println("  "+p.toAbsolutePath())
		Files.list(Path.of("samples", "simple")).forEach(p -> 
			build.addSource(moduleFromPath(p.toString()))
		);
		
//		build.addSource(moduleFromPath("samples/nfv/etsi-nfv-descriptors.yang"));
		
		SchemaContext schemaContext = build.buildEffective();
//		
//		Set<Module> modules = schemaContext.getModules();
@@ -74,6 +231,15 @@ public class Yang2TDLTranslator {
		expand("  ", schemaContext);
	}


	private static CrossSourceStatementReactor createReactor() {
		CrossSourceStatementReactor reactor = RFC7950Reactors.vanillaReactorBuilder()
        .addStatementSupport(ModelProcessingPhase.FULL_DECLARATION,
            new MountStatementSupport(YangParserConfiguration.DEFAULT))
        .build();
		return reactor;
	}

	private static void processStatic(CrossSourceStatementReactor reactor) throws ReactorException {
		reactor.newBuild().addSources(
//                moduleFromResources("/ietf/ietf-yang-types@2013-07-15.yang"),
@@ -140,13 +306,19 @@ public class Yang2TDLTranslator {
		if (c instanceof LeafListSchemaNode) {
			System.out.println(prefix+c.getQName().getLocalName() + " : " + ((LeafListSchemaNode) c).getType().getQName());
		} else if (c instanceof ContainerSchemaNode) {
			System.out.println("!c"+prefix+c.getQName().getLocalName() + " : " );
			//create structured data type
			expand(prefix+"  ", (ContainerSchemaNode) c);
		} else if (c instanceof ListSchemaNode) {
			System.out.println("!l"+prefix+c.getQName().getLocalName() + " : " );
			//create collection of structured data type
			expand(prefix+"  ", (ListSchemaNode) c);
		} else if (c instanceof RegularLeafEffectiveStatement) {
			System.out.println("!r"+prefix+c.getQName().getLocalName() + " : " + ((RegularLeafEffectiveStatement) c).getDeclared().getType().argument());
			//create member of reference data type?
		} else if (c instanceof EmptyLeafEffectiveStatement) {
			System.out.println("!e"+prefix+c.getQName().getLocalName() + " : " + ((EmptyLeafEffectiveStatement) c).getType().getQName());
			//create member of data type?
		} else if (c instanceof LeafrefTypeDefinition) {
			//not working?
			System.out.println(((LeafrefTypeDefinition) c).getPathStatement().getOriginalString());
@@ -155,7 +327,7 @@ public class Yang2TDLTranslator {
			String t = type.getQName().getLocalName();
			if (!type.getQName().getLocalName().equals("string")) {
				t = type.getQName().toString();
//				System.out.println("!x"+((Default<QName,LeafStatement>) c).getDeclared().getType());
				System.out.println("!x"+((Default<QName,LeafStatement>) c).getDeclared().getType());
			} 
			System.out.println("!"+prefix+c.getQName().getLocalName() + " : " + t);
		} else {