Commit 52605ea4 authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ refinement and extension of yang translator

parent 37d298f6
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -10,7 +10,10 @@ import org.etsi.mts.tdl.helper.TDLHelper;

public class YANGConverter {
	public static void main(String[] args) {
		String inputPath = "samples/sports.yang";
		String inputPath = "samples/simple/sports.yang";
//		inputPath = "samples/simple/links.yang";
//		inputPath = "samples/simple/example.yang";
//		inputPath = "samples/simple/acme.yang";
		String output = processToString(inputPath, inputPath+".tdltx");
		System.out.println(output);
	}
+77 −80
Original line number Diff line number Diff line
@@ -5,14 +5,15 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
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.EnumDataType;
import org.etsi.mts.tdl.Extension;
import org.etsi.mts.tdl.Member;
import org.etsi.mts.tdl.SimpleDataInstance;
import org.etsi.mts.tdl.SimpleDataType;
import org.etsi.mts.tdl.StructuredDataInstance;
import org.etsi.mts.tdl.StructuredDataType;
import org.etsi.mts.tdl.tdlFactory;
import org.etsi.mts.tdl.tdlPackage;
@@ -22,18 +23,19 @@ 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.DataNodeContainer;
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;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
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.EnumTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
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.type.BaseTypes;
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;
@@ -46,10 +48,8 @@ import org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors;
import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
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 {

@@ -70,9 +70,10 @@ public class Yang2TDLTranslator extends AbstractTranslator {
//		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()))
		);
//		Files.list(Path.of("samples", "simple")).forEach(p -> 
//			build.addSource(moduleFromPath(p.toString()))
//		);
		build.addSource(moduleFromPath(targetFilename));
		SchemaContext schemaContext = build.buildEffective();
		//TODO: handle multimodule paths?
		//TODO: include meta-data
@@ -86,21 +87,6 @@ public class Yang2TDLTranslator extends AbstractTranslator {
		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) {
@@ -114,40 +100,28 @@ public class Yang2TDLTranslator extends AbstractTranslator {
			name = parent+"___"+name;
		}
		if (c instanceof ContainerSchemaNode) {
			//DONE: remove wrapper container structured data type of only a collection is contained
			Collection<? extends DataSchemaNode> childNodes = ((ContainerSchemaNode) c).getChildNodes();
			DataSchemaNode first = childNodes.iterator().next();
			if (childNodes.size() == 1 && first instanceof ListSchemaNode) {
				//create collection
				return translate(first, parent); //parent?
			} else {
				//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, baseName);
				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);
				}
			}
				StructuredDataType dataType = translate((ContainerSchemaNode) c, baseName, name);
				return dataType;
			}
			
		} else if (c instanceof ListSchemaNode) {
			//TODO: add key annotation?
			System.out.println("!l "+c.getQName().getLocalName() + " : " );
			StructuredDataType itemType = getStructuredDataTypeFor(name);
			StructuredDataType itemType = translate((ListSchemaNode) c, baseName, 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, baseName);
				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() + " : " );
			//DONE: unify and reuse
			String typeName = ((EmptyLeafListEffectiveStatement) c).getType().getQName().getLocalName();
			SimpleDataType itemType = getSimpleDataTypeFor(typeName);
			CollectionDataType collectionType = getTypeFor(itemType.getName() + "_collection",
@@ -155,44 +129,62 @@ public class Yang2TDLTranslator extends AbstractTranslator {
			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);
//			}
			//TODO: check and remove?
			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();
			typeName = name; //TODO: fine?
			TypeDefinition<?> type = ((EmptyLeafEffectiveStatement) c).getType();
			TypeDefinition<?> baseType = type.getBaseType();
			String typeName = type.getQName().getLocalName();
			typeName = name; //DONE: fine? -> seems to be
			if (baseType instanceof EnumTypeDefinition) { 
				//DONE: handle enumeration -> add instances rather than extension
				EnumDataType dataType = getEnumDataTypeFor(typeName);
				for (EnumPair e : ((EnumTypeDefinition)baseType).getValues()) {
					SimpleDataInstance eInstance = getSimpleDataInstanceFor(e.getName());
					eInstance.setDataType(dataType);
					dataType.getValue().add(eInstance);
				}
				//TODO: add default?
				return dataType;
			} else {
				//TODO: add constraints?
				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
					//add 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());
			//TODO: what is the difference? is it used
			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()) {
				translateMember(baseName, dataType, child);
			}
			return dataType;
		} else {
			System.out.println("TODO:: "+c);
			SimpleDataType todoType = getSimpleDataTypeFor("TODO");
			return todoType;
		}
	}


	private void translateMember(String baseName, StructuredDataType dataType, DataSchemaNode child) {
		DataType memberType = translate(child, baseName);
		String propertyName = child.getQName().getLocalName();
		Member m = getContentWithName((String) propertyName, dataType, tdlPackage.Literals.MEMBER);
@@ -201,14 +193,19 @@ public class Yang2TDLTranslator extends AbstractTranslator {
			dataType.getMember().add(m);
		}
	}
			return dataType;
		} else {
			System.out.println(c);
			SimpleDataType todoType = getSimpleDataTypeFor("TODO");
			return todoType;


	private StructuredDataType translate(DataNodeContainer c, String baseName, String name) {
		StructuredDataType dataType = getStructuredDataTypeFor(name);
		for (DataSchemaNode child : c.getChildNodes()) {
			translateMember(baseName, dataType, child);
		}
		return dataType;
	}
	
	//----------------------------------------------------------
	//TODO: clean up below
	
	
	public static void main(String[] args) throws Exception {
        CrossSourceStatementReactor reactor = createReactor();