Commit 38cace10 authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ refinements to yang translator

parent c967afdb
Loading
Loading
Loading
Loading
+119 −46
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import org.etsi.mts.tdl.CollectionDataType;
import org.etsi.mts.tdl.DataType;
@@ -30,17 +32,23 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
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.IdentityrefTypeDefinition;
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.DeclaredCaseEffectiveStatement;
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.RegularChoiceEffectiveStatement;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.RegularLeafEffectiveStatement;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.RegularLeafListEffectiveStatement;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.SlimLeafListEffectiveStatement;
import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.UndeclaredCaseEffectiveStatement;
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;
@@ -53,6 +61,10 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementR

public class Yang2TDLTranslator extends AbstractTranslator {

    private static final String REFERENCE_DESCRIPTION = "ReferenceDescription";
	private static final String LIST_KEY = "ListKey";
	private static final String LEAF_REF_PATH = "LeafRefPath";

	//inherited entry point
	@Override
	public void translate(String targetFilename) throws Exception {
@@ -67,13 +79,16 @@ public class Yang2TDLTranslator extends AbstractTranslator {
		Files.list(Path.of("samples", "ietf")).forEach(p -> 
			build.addLibSource(moduleFromPath(p.toString()))
		);
//		Files.list(Path.of("samples", "nfv")).forEach(p -> 
		Files.list(Path.of("samples", "nfv")).forEach(p -> 
			build.addSource(moduleFromPath(p.toString()))
		);
//		Files.list(Path.of("samples", "mwt")).forEach(p -> 
//			build.addSource(moduleFromPath(p.toString()))
//		);
//		Files.list(Path.of("samples", "simple")).forEach(p -> 
//			build.addSource(moduleFromPath(p.toString()))
//		);
		build.addSource(moduleFromPath(targetFilename));
//		build.addSource(moduleFromPath(targetFilename));
		SchemaContext schemaContext = build.buildEffective();
		//TODO: handle multimodule paths?
		//TODO: include meta-data
@@ -94,6 +109,18 @@ public class Yang2TDLTranslator extends AbstractTranslator {
	}
	
	private DataType translate(DataSchemaNode c, String parent) {
		//wrapper for meta-data
		//TODO: make optional
		//TODO: resolve issues with annotations
		//TODO: use notes?
		DataType dataType = translateOnly(c, parent);
//		c.getDescription().ifPresent(e-> {
//			annotateWith(dataType, REFERENCE_DESCRIPTION, e);
//		});
		return dataType;
	}
	
	private DataType translateOnly(DataSchemaNode c, String parent) {
		String baseName = cleanName(c.getQName().getLocalName());
		String name = baseName;
		if (parent != null) {
@@ -108,38 +135,94 @@ public class Yang2TDLTranslator extends AbstractTranslator {
				return translate(first, parent); //parent?
			} else {
				//create structured data type
				StructuredDataType dataType = translate((ContainerSchemaNode) c, baseName, name);
				StructuredDataType dataType = translateStructuredDataType((ContainerSchemaNode) c, baseName, name);
				return dataType;
			}
			
		} else if (c instanceof ListSchemaNode) {
			StructuredDataType itemType = translateStructuredDataType((ListSchemaNode) c, baseName, name);
			CollectionDataType collectionType = getCollectionDataTypeFor(itemType);

			//TODO: add key annotation?
			StructuredDataType itemType = translate((ListSchemaNode) c, baseName, name);
			CollectionDataType collectionType = getTypeFor(itemType.getName() + "_collection",
					tdlPackage.Literals.COLLECTION_DATA_TYPE);
			collectionType.setItemType(itemType);
			List<QName> keyDefinition = ((ListSchemaNode) c).getKeyDefinition();
			String key = keyDefinition.stream()
					.map(QName::getLocalName)
					.collect(Collectors.joining(", "));
			// TODO: make optional
//			annotateWith(collectionType, LIST_KEY, key);
			return collectionType;
		} else if (c instanceof RegularLeafListEffectiveStatement) {
			//TODO: what is the difference?
			TypeDefinition<?> type = ((RegularLeafListEffectiveStatement) c).getType();
			CollectionDataType collectionType = translateSimpleDataCollection(name, type);
			return collectionType;
			//create collection of structured data type
		} else if (c instanceof EmptyLeafListEffectiveStatement) {
			//DONE: unify and reuse
			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);
			TypeDefinition<?> type = ((EmptyLeafListEffectiveStatement) c).getType();
			CollectionDataType collectionType = translateSimpleDataCollection(name, type);
			return collectionType;
		} else if (c instanceof SlimLeafListEffectiveStatement) {
			//TODO: check and remove?
			SimpleDataType itemType = getSimpleDataTypeFor("TODO");
			CollectionDataType collectionType = getTypeFor(itemType.getName() + "_collection",
					tdlPackage.Literals.COLLECTION_DATA_TYPE);
			collectionType.setItemType(itemType);
			TypeDefinition<?> type = ((SlimLeafListEffectiveStatement) c).getType();
			CollectionDataType collectionType = translateSimpleDataCollection(name, type);
			return collectionType;
		} else if (c instanceof EmptyLeafEffectiveStatement) {
			TypeDefinition<?> type = ((EmptyLeafEffectiveStatement) c).getType();
			SimpleDataType dataType = translateSimpleDataType(name, type);
			return dataType;
		} else if (c instanceof RegularLeafEffectiveStatement) {
			//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 RegularChoiceEffectiveStatement) {
			//TODO: difference?
			StructuredDataType dataType = getStructuredDataTypeFor(name);
			for (CaseSchemaNode child : ((RegularChoiceEffectiveStatement) c).getCases()) {
				translateMember(baseName, dataType, child);
			}
			return dataType;
		} else if (c instanceof EmptyChoiceEffectiveStatement) {
			//TODO: add annotation choice
			//TODO: need to skip cases?
			//TODO: structured or simple?!
			StructuredDataType dataType = getStructuredDataTypeFor(name);
			for (CaseSchemaNode child : ((EmptyChoiceEffectiveStatement) c).getCases()) {
				translateMember(baseName, dataType, child);
			}
			return dataType;
		} else if (c instanceof UndeclaredCaseEffectiveStatement) {
			//choice -> container? (no case)
			return translateStructuredDataType((DataNodeContainer) c, baseName, name);
		} else if (c instanceof DeclaredCaseEffectiveStatement) {
			//choice -> case
			//TODO: compare and check
			return translateStructuredDataType((DataNodeContainer) c, baseName, name);
		} else {
			System.out.println("TODO:: "+c);
			SimpleDataType todoType = getSimpleDataTypeFor("TODO");
			return todoType;
		}
	}

	private CollectionDataType translateSimpleDataCollection(String name, TypeDefinition<?> type) {
		SimpleDataType itemType = translateSimpleDataType(name, type);
		CollectionDataType collectionType = getCollectionDataTypeFor(itemType);
		return collectionType;
	}

	private SimpleDataType translateSimpleDataType(String name, TypeDefinition<?> type) {
		if (type instanceof IdentityrefTypeDefinition) {
			//TODO: handle further?
//			System.out.println("identityref:"+name+" -> "+((IdentityrefTypeDefinition)type).getIdentities());
		}
		if (type instanceof LeafrefTypeDefinition) {
			//TODO: handle further?
//			System.out.println("leafref:"+name+" -> "+((LeafrefTypeDefinition)type).getPathStatement().getOriginalString());
		}

		TypeDefinition<?> baseType = type.getBaseType();
		String typeName = type.getQName().getLocalName();
			typeName = name; //DONE: fine? -> seems to be
//		typeName = name; //DONE: fine? -> seems to be -> causes lots of redundant types
		if (baseType instanceof EnumTypeDefinition) { 
			//DONE: handle enumeration -> add instances rather than extension
			EnumDataType dataType = getEnumDataTypeFor(typeName);
@@ -163,24 +246,6 @@ public class Yang2TDLTranslator extends AbstractTranslator {
			}
			return dataType;
		}
		} else if (c instanceof RegularLeafEffectiveStatement) {
			//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) {
			//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;
		}
	}


@@ -192,10 +257,18 @@ public class Yang2TDLTranslator extends AbstractTranslator {
		if (m.container() == null) {
			dataType.getMember().add(m);
		}
		
		if (child instanceof TypedDataSchemaNode) {
			TypeDefinition<?> type = ((TypedDataSchemaNode) child).getType();
			if (type instanceof LeafrefTypeDefinition) {
				String value = ((LeafrefTypeDefinition)type).getPathStatement().getOriginalString();
				annotateWith(m, LEAF_REF_PATH, value);
			}
		}
	}


	private StructuredDataType translate(DataNodeContainer c, String baseName, String name) {
	private StructuredDataType translateStructuredDataType(DataNodeContainer c, String baseName, String name) {
		StructuredDataType dataType = getStructuredDataTypeFor(name);
		for (DataSchemaNode child : c.getChildNodes()) {
			translateMember(baseName, dataType, child);