2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.sal.binding.generator.impl;
10 import static org.opendaylight.controller.binding.generator.util.BindingGeneratorUtil.*;
11 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findDataSchemaNode;
12 import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findParentModule;
14 import java.util.concurrent.Future;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.HashMap;
20 import java.util.List;
24 import org.opendaylight.controller.binding.generator.util.ReferencedTypeImpl;
25 import org.opendaylight.controller.binding.generator.util.Types;
26 import org.opendaylight.controller.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
27 import org.opendaylight.controller.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
28 import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
29 import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider;
30 import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
31 import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
32 import org.opendaylight.controller.sal.binding.model.api.Type;
33 import org.opendaylight.controller.sal.binding.model.api.type.builder.EnumBuilder;
34 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
35 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTOBuilder;
36 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
37 import org.opendaylight.controller.sal.binding.model.api.type.builder.MethodSignatureBuilder;
38 import org.opendaylight.controller.sal.binding.yang.types.TypeProviderImpl;
39 import org.opendaylight.controller.yang.binding.Notification;
40 import org.opendaylight.controller.yang.common.QName;
41 import org.opendaylight.controller.yang.common.RpcResult;
42 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
43 import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
44 import org.opendaylight.controller.yang.model.api.ChoiceNode;
45 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
46 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
47 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
48 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
49 import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
50 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
51 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
52 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
53 import org.opendaylight.controller.yang.model.api.Module;
54 import org.opendaylight.controller.yang.model.api.NotificationDefinition;
55 import org.opendaylight.controller.yang.model.api.RpcDefinition;
56 import org.opendaylight.controller.yang.model.api.SchemaContext;
57 import org.opendaylight.controller.yang.model.api.SchemaNode;
58 import org.opendaylight.controller.yang.model.api.SchemaPath;
59 import org.opendaylight.controller.yang.model.api.TypeDefinition;
60 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;
61 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
62 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
63 import org.opendaylight.controller.yang.model.util.DataNodeIterator;
64 import org.opendaylight.controller.yang.model.util.ExtendedType;
65 import org.opendaylight.controller.yang.model.util.SchemaContextUtil;
66 import org.opendaylight.controller.yang.model.util.UnionType;
68 public final class BindingGeneratorImpl implements BindingGenerator {
70 private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders;
71 private TypeProvider typeProvider;
72 private SchemaContext schemaContext;
74 public BindingGeneratorImpl() {
79 public List<Type> generateTypes(final SchemaContext context) {
80 if (context == null) {
81 throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
83 if (context.getModules() == null) {
84 throw new IllegalStateException("Schema Context does not contain defined modules!");
87 final List<Type> generatedTypes = new ArrayList<>();
88 schemaContext = context;
89 typeProvider = new TypeProviderImpl(context);
90 final Set<Module> modules = context.getModules();
91 genTypeBuilders = new HashMap<>();
92 for (final Module module : modules) {
93 generatedTypes.add(moduleToDataType(module));
94 generatedTypes.addAll(allTypeDefinitionsToGenTypes(module));
95 generatedTypes.addAll(allContainersToGenTypes(module));
96 generatedTypes.addAll(allListsToGenTypes(module));
97 generatedTypes.addAll(allChoicesToGenTypes(module));
98 generatedTypes.addAll(allAugmentsToGenTypes(module));
99 generatedTypes.addAll(allRPCMethodsToGenType(module));
100 generatedTypes.addAll(allNotificationsToGenType(module));
101 generatedTypes.addAll(allIdentitiesToGenTypes(module, context));
102 generatedTypes.addAll(allGroupingsToGenTypes(module));
104 return generatedTypes;
108 public List<Type> generateTypes(final SchemaContext context, final Set<Module> modules) {
109 if (context == null) {
110 throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
112 if (context.getModules() == null) {
113 throw new IllegalStateException("Schema Context does not contain defined modules!");
115 if (modules == null) {
116 throw new IllegalArgumentException("Sef of Modules cannot be NULL!");
119 final List<Type> filteredGenTypes = new ArrayList<>();
120 schemaContext = context;
121 typeProvider = new TypeProviderImpl(context);
122 final Set<Module> contextModules = context.getModules();
123 genTypeBuilders = new HashMap<>();
124 for (final Module contextModule : contextModules) {
125 final List<Type> generatedTypes = new ArrayList<>();
127 generatedTypes.add(moduleToDataType(contextModule));
128 generatedTypes.addAll(allTypeDefinitionsToGenTypes(contextModule));
129 generatedTypes.addAll(allContainersToGenTypes(contextModule));
130 generatedTypes.addAll(allListsToGenTypes(contextModule));
131 generatedTypes.addAll(allChoicesToGenTypes(contextModule));
132 generatedTypes.addAll(allAugmentsToGenTypes(contextModule));
133 generatedTypes.addAll(allRPCMethodsToGenType(contextModule));
134 generatedTypes.addAll(allNotificationsToGenType(contextModule));
135 generatedTypes.addAll(allIdentitiesToGenTypes(contextModule, context));
136 generatedTypes.addAll(allGroupingsToGenTypes(contextModule));
138 if (modules.contains(contextModule)) {
139 filteredGenTypes.addAll(generatedTypes);
142 return filteredGenTypes;
145 private List<Type> allTypeDefinitionsToGenTypes(final Module module) {
146 if (module == null) {
147 throw new IllegalArgumentException("Module reference cannot be NULL!");
149 if (module.getName() == null) {
150 throw new IllegalArgumentException("Module name cannot be NULL!");
152 if (module.getTypeDefinitions() == null) {
153 throw new IllegalArgumentException("Type Definitions for module " + module.getName() + " cannot be NULL!");
156 final Set<TypeDefinition<?>> typeDefinitions = module.getTypeDefinitions();
157 final List<Type> generatedTypes = new ArrayList<>();
158 for (final TypeDefinition<?> typedef : typeDefinitions) {
159 if (typedef != null) {
160 final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef);
161 if ((type != null) && !generatedTypes.contains(type)) {
162 generatedTypes.add(type);
166 return generatedTypes;
169 private List<Type> allContainersToGenTypes(final Module module) {
170 if (module == null) {
171 throw new IllegalArgumentException("Module reference cannot be NULL!");
174 if (module.getName() == null) {
175 throw new IllegalArgumentException("Module name cannot be NULL!");
178 if (module.getChildNodes() == null) {
179 throw new IllegalArgumentException("Reference to Set of Child Nodes in module " + module.getName()
180 + " cannot be NULL!");
183 final List<Type> generatedTypes = new ArrayList<>();
184 final DataNodeIterator it = new DataNodeIterator(module);
185 final List<ContainerSchemaNode> schemaContainers = it.allContainers();
186 final String basePackageName = moduleNamespaceToPackageName(module);
187 for (final ContainerSchemaNode container : schemaContainers) {
188 generatedTypes.add(containerToGenType(basePackageName, container));
190 return generatedTypes;
193 private List<Type> allListsToGenTypes(final Module module) {
194 if (module == null) {
195 throw new IllegalArgumentException("Module reference cannot be NULL!");
198 if (module.getName() == null) {
199 throw new IllegalArgumentException("Module name cannot be NULL!");
202 if (module.getChildNodes() == null) {
203 throw new IllegalArgumentException("Reference to Set of Child Nodes in module " + module.getName()
204 + " cannot be NULL!");
207 final List<Type> generatedTypes = new ArrayList<>();
208 final DataNodeIterator it = new DataNodeIterator(module);
209 final List<ListSchemaNode> schemaLists = it.allLists();
210 final String basePackageName = moduleNamespaceToPackageName(module);
211 if (schemaLists != null) {
212 for (final ListSchemaNode list : schemaLists) {
213 generatedTypes.addAll(listToGenType(basePackageName, list));
216 return generatedTypes;
219 private List<GeneratedType> allChoicesToGenTypes(final Module module) {
220 if (module == null) {
221 throw new IllegalArgumentException("Module reference cannot be NULL!");
223 if (module.getName() == null) {
224 throw new IllegalArgumentException("Module name cannot be NULL!");
227 final DataNodeIterator it = new DataNodeIterator(module);
228 final List<ChoiceNode> choiceNodes = it.allChoices();
229 final String basePackageName = moduleNamespaceToPackageName(module);
231 final List<GeneratedType> generatedTypes = new ArrayList<>();
232 for (final ChoiceNode choice : choiceNodes) {
233 if (choice != null) {
234 generatedTypes.addAll(choiceToGeneratedType(basePackageName, choice));
237 return generatedTypes;
240 private List<Type> allAugmentsToGenTypes(final Module module) {
241 if (module == null) {
242 throw new IllegalArgumentException("Module reference cannot be NULL!");
244 if (module.getName() == null) {
245 throw new IllegalArgumentException("Module name cannot be NULL!");
247 if (module.getChildNodes() == null) {
248 throw new IllegalArgumentException("Reference to Set of Augmentation Definitions in module "
249 + module.getName() + " cannot be NULL!");
252 final List<Type> generatedTypes = new ArrayList<>();
253 final String basePackageName = moduleNamespaceToPackageName(module);
254 final List<AugmentationSchema> augmentations = resolveAugmentations(module);
255 for (final AugmentationSchema augment : augmentations) {
256 generatedTypes.addAll(augmentationToGenTypes(basePackageName, augment));
258 return generatedTypes;
261 private List<AugmentationSchema> resolveAugmentations(final Module module) {
262 if (module == null) {
263 throw new IllegalArgumentException("Module reference cannot be NULL!");
265 if (module.getAugmentations() == null) {
266 throw new IllegalStateException("Augmentations Set cannot be NULL!");
269 final Set<AugmentationSchema> augmentations = module.getAugmentations();
270 final List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);
271 Collections.sort(sortedAugmentations, new Comparator<AugmentationSchema>() {
274 public int compare(AugmentationSchema augSchema1, AugmentationSchema augSchema2) {
276 if (augSchema1.getTargetPath().getPath().size() > augSchema2.getTargetPath().getPath().size()) {
278 } else if (augSchema1.getTargetPath().getPath().size() < augSchema2.getTargetPath().getPath().size()) {
286 return sortedAugmentations;
289 private GeneratedType moduleToDataType(final Module module) {
290 if (module == null) {
291 throw new IllegalArgumentException("Module reference cannot be NULL!");
294 final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");
296 final String basePackageName = moduleNamespaceToPackageName(module);
297 if (moduleDataTypeBuilder != null) {
298 final Set<DataSchemaNode> dataNodes = module.getChildNodes();
299 resolveDataSchemaNodes(basePackageName, moduleDataTypeBuilder, dataNodes);
301 return moduleDataTypeBuilder.toInstance();
304 private List<Type> allRPCMethodsToGenType(final Module module) {
305 if (module == null) {
306 throw new IllegalArgumentException("Module reference cannot be NULL!");
309 if (module.getName() == null) {
310 throw new IllegalArgumentException("Module name cannot be NULL!");
313 if (module.getChildNodes() == null) {
314 throw new IllegalArgumentException("Reference to Set of RPC Method Definitions in module "
315 + module.getName() + " cannot be NULL!");
318 final String basePackageName = moduleNamespaceToPackageName(module);
319 final Set<RpcDefinition> rpcDefinitions = module.getRpcs();
320 final List<Type> genRPCTypes = new ArrayList<>();
321 final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service");
322 final Type future = Types.typeForClass(Future.class);
323 for (final RpcDefinition rpc : rpcDefinitions) {
326 String rpcName = parseToClassName(rpc.getQName().getLocalName());
327 String rpcMethodName = parseToValidParamName(rpcName);
328 MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName);
330 final List<DataNodeIterator> rpcInOut = new ArrayList<>();
332 ContainerSchemaNode input = rpc.getInput();
333 ContainerSchemaNode output = rpc.getOutput();
336 rpcInOut.add(new DataNodeIterator(input));
337 GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName);
338 resolveDataSchemaNodes(basePackageName, inType, input.getChildNodes());
339 Type inTypeInstance = inType.toInstance();
340 genRPCTypes.add(inTypeInstance);
341 method.addParameter(inTypeInstance, "input");
344 Type outTypeInstance = Types.typeForClass(Void.class);
345 if (output != null) {
346 rpcInOut.add(new DataNodeIterator(output));
348 GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName);
349 resolveDataSchemaNodes(basePackageName, outType, output.getChildNodes());
350 outTypeInstance = outType.toInstance();
351 genRPCTypes.add(outTypeInstance);
355 final Type rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class), outTypeInstance);
356 method.setReturnType(Types.parameterizedTypeFor(future, rpcRes));
357 for (DataNodeIterator it : rpcInOut) {
358 List<ContainerSchemaNode> nContainers = it.allContainers();
359 if ((nContainers != null) && !nContainers.isEmpty()) {
360 for (final ContainerSchemaNode container : nContainers) {
361 genRPCTypes.add(containerToGenType(basePackageName, container));
364 List<ListSchemaNode> nLists = it.allLists();
365 if ((nLists != null) && !nLists.isEmpty()) {
366 for (final ListSchemaNode list : nLists) {
367 genRPCTypes.addAll(listToGenType(basePackageName, list));
373 genRPCTypes.add(interfaceBuilder.toInstance());
377 private List<Type> allNotificationsToGenType(final Module module) {
378 if (module == null) {
379 throw new IllegalArgumentException("Module reference cannot be NULL!");
382 if (module.getName() == null) {
383 throw new IllegalArgumentException("Module name cannot be NULL!");
386 if (module.getChildNodes() == null) {
387 throw new IllegalArgumentException("Reference to Set of Notification Definitions in module "
388 + module.getName() + " cannot be NULL!");
391 final String basePackageName = moduleNamespaceToPackageName(module);
392 final List<Type> genNotifyTypes = new ArrayList<>();
393 final Set<NotificationDefinition> notifications = module.getNotifications();
395 for (final NotificationDefinition notification : notifications) {
396 if (notification != null) {
397 DataNodeIterator it = new DataNodeIterator(notification);
400 for (ContainerSchemaNode node : it.allContainers()) {
401 genNotifyTypes.add(containerToGenType(basePackageName, node));
404 for (ListSchemaNode node : it.allLists()) {
405 genNotifyTypes.addAll(listToGenType(basePackageName, node));
407 final GeneratedTypeBuilder notificationTypeBuilder = addDefaultInterfaceDefinition(basePackageName,
409 notificationTypeBuilder.addImplementsType(Types.typeForClass(Notification.class));
410 // Notification object
411 resolveDataSchemaNodes(basePackageName, notificationTypeBuilder, notification.getChildNodes());
412 genNotifyTypes.add(notificationTypeBuilder.toInstance());
415 return genNotifyTypes;
418 private List<Type> allIdentitiesToGenTypes(final Module module, final SchemaContext context) {
419 List<Type> genTypes = new ArrayList<>();
421 final Set<IdentitySchemaNode> schemaIdentities = module.getIdentities();
423 final String basePackageName = moduleNamespaceToPackageName(module);
425 if (schemaIdentities != null && !schemaIdentities.isEmpty()) {
426 for (final IdentitySchemaNode identity : schemaIdentities) {
427 genTypes.add(identityToGenType(basePackageName, identity, context));
433 private GeneratedType identityToGenType(final String basePackageName, final IdentitySchemaNode identity,
434 final SchemaContext context) {
435 if (identity == null) {
439 final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
440 final String genTypeName = parseToClassName(identity.getQName().getLocalName());
441 final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTypeName);
443 IdentitySchemaNode baseIdentity = identity.getBaseIdentity();
444 if (baseIdentity != null) {
445 Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);
447 final String returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule);
448 final String returnTypeName = parseToClassName(baseIdentity.getQName().getLocalName());
450 GeneratedTransferObject gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName).toInstance();
451 newType.setExtendsType(gto);
453 newType.setExtendsType(Types.getBaseIdentityTO());
455 newType.setAbstract(true);
456 return newType.toInstance();
459 private List<Type> allGroupingsToGenTypes(final Module module) {
460 final List<Type> genTypes = new ArrayList<>();
461 final String basePackageName = moduleNamespaceToPackageName(module);
462 final Set<GroupingDefinition> groupings = module.getGroupings();
463 if (groupings != null && !groupings.isEmpty()) {
464 for (final GroupingDefinition grouping : groupings) {
465 genTypes.add(groupingToGenType(basePackageName, grouping));
471 private GeneratedType groupingToGenType(final String basePackageName, GroupingDefinition grouping) {
472 if (grouping == null) {
476 final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath());
477 final Set<DataSchemaNode> schemaNodes = grouping.getChildNodes();
478 final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, grouping);
480 resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);
481 return typeBuilder.toInstance();
484 private EnumTypeDefinition enumTypeDefFromExtendedType(final TypeDefinition<?> typeDefinition) {
485 if (typeDefinition != null) {
486 if (typeDefinition.getBaseType() instanceof EnumTypeDefinition) {
487 return (EnumTypeDefinition) typeDefinition.getBaseType();
488 } else if (typeDefinition.getBaseType() instanceof ExtendedType) {
489 return enumTypeDefFromExtendedType(typeDefinition.getBaseType());
495 private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final String enumName,
496 final GeneratedTypeBuilder typeBuilder) {
497 if ((enumTypeDef != null) && (typeBuilder != null) && (enumTypeDef.getQName() != null)
498 && (enumTypeDef.getQName().getLocalName() != null)) {
500 final String enumerationName = parseToClassName(enumName);
501 final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
503 if (enumBuilder != null) {
504 final List<EnumPair> enums = enumTypeDef.getValues();
507 for (final EnumPair enumPair : enums) {
508 if (enumPair != null) {
509 final String enumPairName = parseToClassName(enumPair.getName());
510 Integer enumPairValue = enumPair.getValue();
512 if (enumPairValue == null) {
513 enumPairValue = listIndex;
515 enumBuilder.addValue(enumPairName, enumPairValue);
526 private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) {
527 if (module == null) {
528 throw new IllegalArgumentException("Module reference cannot be NULL!");
530 String packageName = moduleNamespaceToPackageName(module);
531 final String moduleName = parseToClassName(module.getName()) + postfix;
533 return new GeneratedTypeBuilderImpl(packageName, moduleName);
537 private List<Type> augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema) {
538 if (augmentPackageName == null) {
539 throw new IllegalArgumentException("Package Name cannot be NULL!");
541 if (augSchema == null) {
542 throw new IllegalArgumentException("Augmentation Schema cannot be NULL!");
544 if (augSchema.getTargetPath() == null) {
545 throw new IllegalStateException("Augmentation Schema does not contain Target Path (Target Path is NULL).");
548 final List<Type> genTypes = new ArrayList<>();
550 // EVERY augmented interface will extends Augmentation<T> interface
551 // and DataObject interface!!!
552 final SchemaPath targetPath = augSchema.getTargetPath();
553 final DataSchemaNode targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
554 if ((targetSchemaNode != null) && (targetSchemaNode.getQName() != null)
555 && (targetSchemaNode.getQName().getLocalName() != null)) {
556 final Module targetModule = findParentModule(schemaContext, targetSchemaNode);
557 final String targetBasePackage = moduleNamespaceToPackageName(targetModule);
558 final String targetPackageName = packageNameForGeneratedType(targetBasePackage, targetSchemaNode.getPath());
559 final String targetSchemaNodeName = targetSchemaNode.getQName().getLocalName();
560 final Set<DataSchemaNode> augChildNodes = augSchema.getChildNodes();
562 if (!(targetSchemaNode instanceof ChoiceNode)) {
563 final GeneratedTypeBuilder augTypeBuilder = addRawAugmentGenTypeDefinition(augmentPackageName,
564 targetPackageName, targetSchemaNodeName, augSchema);
565 final GeneratedType augType = augTypeBuilder.toInstance();
566 genTypes.add(augType);
568 final Type refChoiceType = new ReferencedTypeImpl(targetPackageName,
569 parseToClassName(targetSchemaNodeName));
570 final ChoiceNode choiceTarget = (ChoiceNode) targetSchemaNode;
571 final Set<ChoiceCaseNode> choiceCaseNodes = choiceTarget.getCases();
572 genTypes.addAll(augmentCasesToGenTypes(augmentPackageName, refChoiceType, choiceCaseNodes));
574 genTypes.addAll(augmentationBodyToGenTypes(augmentPackageName, augChildNodes));
579 private List<GeneratedType> augmentCasesToGenTypes(final String augmentPackageName, final Type refChoiceType,
580 final Set<ChoiceCaseNode> choiceCaseNodes) {
581 if (augmentPackageName == null) {
582 throw new IllegalArgumentException("Augment Package Name string cannot be NULL!");
584 if (choiceCaseNodes == null) {
585 throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!");
587 final List<GeneratedType> genTypes = generateTypesFromAugmentedChoiceCases(augmentPackageName, refChoiceType,
592 private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final String augmentPackageName,
593 final String targetPackageName, final String targetSchemaNodeName, final AugmentationSchema augSchema) {
594 final String targetTypeName = parseToClassName(targetSchemaNodeName);
595 Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
596 if (augmentBuilders == null) {
597 augmentBuilders = new HashMap<>();
598 genTypeBuilders.put(augmentPackageName, augmentBuilders);
601 final String augTypeName = augGenTypeName(augmentBuilders, targetTypeName);
602 final Type targetTypeRef = new ReferencedTypeImpl(targetPackageName, targetTypeName);
603 final Set<DataSchemaNode> augChildNodes = augSchema.getChildNodes();
605 final GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
607 augTypeBuilder.addImplementsType(Types.DATA_OBJECT);
608 augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
610 augSchemaNodeToMethods(augmentPackageName, augTypeBuilder, augChildNodes);
611 augmentBuilders.put(augTypeName, augTypeBuilder);
612 return augTypeBuilder;
615 private List<Type> augmentationBodyToGenTypes(final String augBasePackageName,
616 final Set<DataSchemaNode> augChildNodes) {
617 final List<Type> genTypes = new ArrayList<>();
618 final List<DataNodeIterator> augSchemaIts = new ArrayList<>();
619 for (final DataSchemaNode childNode : augChildNodes) {
620 if (childNode instanceof DataNodeContainer) {
621 augSchemaIts.add(new DataNodeIterator((DataNodeContainer) childNode));
623 if (childNode instanceof ContainerSchemaNode) {
624 genTypes.add(containerToGenType(augBasePackageName, (ContainerSchemaNode) childNode));
625 } else if (childNode instanceof ListSchemaNode) {
626 genTypes.addAll(listToGenType(augBasePackageName, (ListSchemaNode) childNode));
628 } else if (childNode instanceof ChoiceNode) {
629 final ChoiceNode choice = (ChoiceNode) childNode;
630 for (final ChoiceCaseNode caseNode : choice.getCases()) {
631 augSchemaIts.add(new DataNodeIterator(caseNode));
633 genTypes.addAll(choiceToGeneratedType(augBasePackageName, (ChoiceNode) childNode));
637 for (final DataNodeIterator it : augSchemaIts) {
638 final List<ContainerSchemaNode> augContainers = it.allContainers();
639 final List<ListSchemaNode> augLists = it.allLists();
640 final List<ChoiceNode> augChoices = it.allChoices();
642 if (augContainers != null) {
643 for (final ContainerSchemaNode container : augContainers) {
644 genTypes.add(containerToGenType(augBasePackageName, container));
647 if (augLists != null) {
648 for (final ListSchemaNode list : augLists) {
649 genTypes.addAll(listToGenType(augBasePackageName, list));
652 if (augChoices != null) {
653 for (final ChoiceNode choice : augChoices) {
654 genTypes.addAll(choiceToGeneratedType(augBasePackageName, choice));
661 private String augGenTypeName(final Map<String, GeneratedTypeBuilder> builders, final String genTypeName) {
662 String augTypeName = genTypeName;
665 while ((builders != null) && builders.containsKey(genTypeName + index)) {
668 augTypeName += index;
672 private GeneratedType containerToGenType(final String basePackageName, ContainerSchemaNode containerNode) {
673 if (containerNode == null) {
677 final String packageName = packageNameForGeneratedType(basePackageName, containerNode.getPath());
678 final Set<DataSchemaNode> schemaNodes = containerNode.getChildNodes();
679 final GeneratedTypeBuilder typeBuilder = addDefaultInterfaceDefinition(packageName, containerNode);
681 resolveDataSchemaNodes(basePackageName, typeBuilder, schemaNodes);
682 return typeBuilder.toInstance();
685 private GeneratedTypeBuilder resolveDataSchemaNodes(final String basePackageName,
686 final GeneratedTypeBuilder typeBuilder, final Set<DataSchemaNode> schemaNodes) {
687 if ((schemaNodes != null) && (typeBuilder != null)) {
688 for (final DataSchemaNode schemaNode : schemaNodes) {
689 if (schemaNode.isAugmenting()) {
692 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder);
698 private GeneratedTypeBuilder augSchemaNodeToMethods(final String basePackageName,
699 final GeneratedTypeBuilder typeBuilder, final Set<DataSchemaNode> schemaNodes) {
700 if ((schemaNodes != null) && (typeBuilder != null)) {
701 for (final DataSchemaNode schemaNode : schemaNodes) {
702 if (schemaNode.isAugmenting()) {
703 addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder);
710 private void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode schemaNode,
711 final GeneratedTypeBuilder typeBuilder) {
712 if (schemaNode != null && typeBuilder != null) {
713 if (schemaNode instanceof LeafSchemaNode) {
714 resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) schemaNode);
715 } else if (schemaNode instanceof LeafListSchemaNode) {
716 resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode);
717 } else if (schemaNode instanceof ContainerSchemaNode) {
718 resolveContainerSchemaNode(basePackageName, typeBuilder, (ContainerSchemaNode) schemaNode);
719 } else if (schemaNode instanceof ListSchemaNode) {
720 resolveListSchemaNode(basePackageName, typeBuilder, (ListSchemaNode) schemaNode);
721 } else if (schemaNode instanceof ChoiceNode) {
722 resolveChoiceSchemaNode(basePackageName, typeBuilder, (ChoiceNode) schemaNode);
727 private void resolveChoiceSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,
728 final ChoiceNode choiceNode) {
729 if (basePackageName == null) {
730 throw new IllegalArgumentException("Base Package Name cannot be NULL!");
732 if (typeBuilder == null) {
733 throw new IllegalArgumentException("Generated Type Builder cannot be NULL!");
735 if (choiceNode == null) {
736 throw new IllegalArgumentException("Choice Schema Node cannot be NULL!");
739 final String choiceName = choiceNode.getQName().getLocalName();
740 if (choiceName != null) {
741 final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath());
742 final GeneratedTypeBuilder choiceType = addDefaultInterfaceDefinition(packageName, choiceNode);
743 constructGetter(typeBuilder, choiceName, choiceNode.getDescription(), choiceType);
747 private List<GeneratedType> choiceToGeneratedType(final String basePackageName, final ChoiceNode choiceNode) {
748 if (basePackageName == null) {
749 throw new IllegalArgumentException("Base Package Name cannot be NULL!");
751 if (choiceNode == null) {
752 throw new IllegalArgumentException("Choice Schema Node cannot be NULL!");
755 final List<GeneratedType> generatedTypes = new ArrayList<>();
756 final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath());
757 final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);
758 choiceTypeBuilder.addImplementsType(Types.DATA_OBJECT);
759 final GeneratedType choiceType = choiceTypeBuilder.toInstance();
761 generatedTypes.add(choiceType);
762 final Set<ChoiceCaseNode> caseNodes = choiceNode.getCases();
763 if ((caseNodes != null) && !caseNodes.isEmpty()) {
764 generatedTypes.addAll(generateTypesFromChoiceCases(basePackageName, choiceType, caseNodes));
766 return generatedTypes;
769 private List<GeneratedType> generateTypesFromChoiceCases(final String basePackageName, final Type refChoiceType,
770 final Set<ChoiceCaseNode> caseNodes) {
771 if (basePackageName == null) {
772 throw new IllegalArgumentException("Base Package Name cannot be NULL!");
774 if (refChoiceType == null) {
775 throw new IllegalArgumentException("Referenced Choice Type cannot be NULL!");
777 if (caseNodes == null) {
778 throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!");
781 final List<GeneratedType> generatedTypes = new ArrayList<>();
782 for (final ChoiceCaseNode caseNode : caseNodes) {
783 if (caseNode != null && !caseNode.isAddedByUses()) {
784 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
785 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
786 caseTypeBuilder.addImplementsType(refChoiceType);
788 final Set<DataSchemaNode> childNodes = caseNode.getChildNodes();
789 if (childNodes != null) {
790 resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes);
792 generatedTypes.add(caseTypeBuilder.toInstance());
796 return generatedTypes;
799 private List<GeneratedType> generateTypesFromAugmentedChoiceCases(final String basePackageName,
800 final Type refChoiceType, final Set<ChoiceCaseNode> caseNodes) {
801 if (basePackageName == null) {
802 throw new IllegalArgumentException("Base Package Name cannot be NULL!");
804 if (refChoiceType == null) {
805 throw new IllegalArgumentException("Referenced Choice Type cannot be NULL!");
807 if (caseNodes == null) {
808 throw new IllegalArgumentException("Set of Choice Case Nodes cannot be NULL!");
811 final List<GeneratedType> generatedTypes = new ArrayList<>();
812 for (final ChoiceCaseNode caseNode : caseNodes) {
813 if (caseNode != null && caseNode.isAugmenting()) {
814 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
815 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode);
816 caseTypeBuilder.addImplementsType(refChoiceType);
818 final Set<DataSchemaNode> childNodes = caseNode.getChildNodes();
819 if (childNodes != null) {
820 resolveDataSchemaNodes(basePackageName, caseTypeBuilder, childNodes);
822 generatedTypes.add(caseTypeBuilder.toInstance());
826 return generatedTypes;
829 private boolean resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf) {
830 if ((leaf != null) && (typeBuilder != null)) {
831 final String leafName = leaf.getQName().getLocalName();
832 String leafDesc = leaf.getDescription();
833 if (leafDesc == null) {
837 if (leafName != null) {
838 final TypeDefinition<?> typeDef = leaf.getType();
840 Type returnType = null;
841 if (typeDef instanceof EnumTypeDefinition) {
842 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef);
843 final EnumTypeDefinition enumTypeDef = enumTypeDefFromExtendedType(typeDef);
844 final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leafName,
847 if (enumBuilder != null) {
848 returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName());
850 ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
851 } else if (typeDef instanceof UnionType) {
852 GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName);
853 if (genTOBuilder != null) {
854 returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
856 } else if (typeDef instanceof BitsTypeDefinition) {
857 GeneratedTOBuilder genTOBuilder = addEnclosedTOToTypeBuilder(typeDef, typeBuilder, leafName);
858 if (genTOBuilder != null) {
859 returnType = new ReferencedTypeImpl(genTOBuilder.getPackageName(), genTOBuilder.getName());
862 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef);
864 if (returnType != null) {
865 constructGetter(typeBuilder, leafName, leafDesc, returnType);
873 private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf,
874 boolean isReadOnly) {
875 if ((leaf != null) && (toBuilder != null)) {
876 final String leafName = leaf.getQName().getLocalName();
877 String leafDesc = leaf.getDescription();
878 if (leafDesc == null) {
882 if (leafName != null) {
883 final TypeDefinition<?> typeDef = leaf.getType();
885 // TODO: properly resolve enum types
886 final Type returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef);
888 if (returnType != null) {
889 final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(parseToClassName(leafName));
891 propBuilder.setReadOnly(isReadOnly);
892 propBuilder.setReturnType(returnType);
893 propBuilder.setComment(leafDesc);
895 toBuilder.addEqualsIdentity(propBuilder);
896 toBuilder.addHashIdentity(propBuilder);
897 toBuilder.addToStringProperty(propBuilder);
906 private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node) {
907 if ((node != null) && (typeBuilder != null)) {
908 final String nodeName = node.getQName().getLocalName();
909 String nodeDesc = node.getDescription();
910 if (nodeDesc == null) {
914 if (nodeName != null) {
915 final TypeDefinition<?> type = node.getType();
916 final Type listType = Types.listTypeFor(typeProvider.javaTypeForSchemaDefinitionType(type));
918 constructGetter(typeBuilder, nodeName, nodeDesc, listType);
925 private boolean resolveContainerSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,
926 final ContainerSchemaNode containerNode) {
927 if ((containerNode != null) && (typeBuilder != null)) {
928 final String nodeName = containerNode.getQName().getLocalName();
930 if (nodeName != null) {
931 final String packageName = packageNameForGeneratedType(basePackageName, containerNode.getPath());
933 final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, containerNode);
934 constructGetter(typeBuilder, nodeName, containerNode.getDescription(), rawGenType);
942 private boolean resolveListSchemaNode(final String basePackageName, final GeneratedTypeBuilder typeBuilder,
943 final ListSchemaNode schemaNode) {
944 if ((schemaNode != null) && (typeBuilder != null)) {
945 final String listName = schemaNode.getQName().getLocalName();
947 if (listName != null) {
948 final String packageName = packageNameForGeneratedType(basePackageName, schemaNode.getPath());
949 final GeneratedTypeBuilder rawGenType = addDefaultInterfaceDefinition(packageName, schemaNode);
950 constructGetter(typeBuilder, listName, schemaNode.getDescription(), Types.listTypeFor(rawGenType));
958 * Method instantiates new Generated Type Builder and sets the implements
959 * definitions of Data Object and Augmentable.
962 * Generated Type Package Name
964 * Schema Node definition
965 * @return Generated Type Builder instance for Schema Node definition
967 private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {
968 final GeneratedTypeBuilder builder = addRawInterfaceDefinition(packageName, schemaNode, "");
969 builder.addImplementsType(Types.DATA_OBJECT);
970 builder.addImplementsType(Types.augmentableTypeFor(builder));
980 private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {
981 return addRawInterfaceDefinition(packageName, schemaNode, "");
984 private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
985 final String prefix) {
986 if (schemaNode == null) {
987 throw new IllegalArgumentException("Data Schema Node cannot be NULL!");
989 if (packageName == null) {
990 throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!");
992 if (schemaNode.getQName() == null) {
993 throw new IllegalArgumentException("QName for Data Schema Node cannot be NULL!");
995 final String schemaNodeName = schemaNode.getQName().getLocalName();
996 if (schemaNodeName == null) {
997 throw new IllegalArgumentException("Local Name of QName for Data Schema Node cannot be NULL!");
1000 final String genTypeName;
1001 if (prefix == null) {
1002 genTypeName = parseToClassName(schemaNodeName);
1004 genTypeName = prefix + parseToClassName(schemaNodeName);
1007 final GeneratedTypeBuilder newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
1008 if (!genTypeBuilders.containsKey(packageName)) {
1009 final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();
1010 builders.put(genTypeName, newType);
1011 genTypeBuilders.put(packageName, builders);
1013 final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
1014 if (!builders.containsKey(genTypeName)) {
1015 builders.put(genTypeName, newType);
1021 private String getterMethodName(final String methodName) {
1022 final StringBuilder method = new StringBuilder();
1023 method.append("get");
1024 method.append(parseToClassName(methodName));
1025 return method.toString();
1028 private String setterMethodName(final String methodName) {
1029 final StringBuilder method = new StringBuilder();
1030 method.append("set");
1031 method.append(parseToClassName(methodName));
1032 return method.toString();
1035 private MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder,
1036 final String schemaNodeName, final String comment, final Type returnType) {
1037 final MethodSignatureBuilder getMethod = interfaceBuilder.addMethod(getterMethodName(schemaNodeName));
1039 getMethod.setComment(comment);
1040 getMethod.setReturnType(returnType);
1045 private MethodSignatureBuilder constructSetter(final GeneratedTypeBuilder interfaceBuilder,
1046 final String schemaNodeName, final String comment, final Type parameterType) {
1047 final MethodSignatureBuilder setMethod = interfaceBuilder.addMethod(setterMethodName(schemaNodeName));
1049 setMethod.setComment(comment);
1050 setMethod.addParameter(parameterType, parseToValidParamName(schemaNodeName));
1051 setMethod.setReturnType(Types.voidType());
1056 private List<Type> listToGenType(final String basePackageName, final ListSchemaNode list) {
1057 if (basePackageName == null) {
1058 throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!");
1061 throw new IllegalArgumentException("List Schema Node cannot be NULL!");
1064 final String packageName = packageNameForGeneratedType(basePackageName, list.getPath());
1065 final GeneratedTypeBuilder typeBuilder = resolveListTypeBuilder(packageName, list);
1066 final List<String> listKeys = listKeys(list);
1067 GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, list, listKeys);
1069 final Set<DataSchemaNode> schemaNodes = list.getChildNodes();
1071 for (final DataSchemaNode schemaNode : schemaNodes) {
1072 if (schemaNode.isAugmenting()) {
1075 addSchemaNodeToListBuilders(basePackageName, schemaNode, typeBuilder, genTOBuilder, listKeys);
1077 return typeBuildersToGenTypes(typeBuilder, genTOBuilder);
1080 private void addSchemaNodeToListBuilders(final String basePackageName, final DataSchemaNode schemaNode,
1081 final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List<String> listKeys) {
1082 if (schemaNode == null) {
1083 throw new IllegalArgumentException("Data Schema Node cannot be NULL!");
1086 if (typeBuilder == null) {
1087 throw new IllegalArgumentException("Generated Type Builder cannot be NULL!");
1090 if (schemaNode instanceof LeafSchemaNode) {
1091 final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode;
1092 if (!isPartOfListKey(leaf, listKeys)) {
1093 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
1095 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);
1097 } else if (schemaNode instanceof LeafListSchemaNode) {
1098 resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode);
1099 } else if (schemaNode instanceof ContainerSchemaNode) {
1100 resolveContainerSchemaNode(basePackageName, typeBuilder, (ContainerSchemaNode) schemaNode);
1101 } else if (schemaNode instanceof ListSchemaNode) {
1102 resolveListSchemaNode(basePackageName, typeBuilder, (ListSchemaNode) schemaNode);
1106 private List<Type> typeBuildersToGenTypes(final GeneratedTypeBuilder typeBuilder, GeneratedTOBuilder genTOBuilder) {
1107 final List<Type> genTypes = new ArrayList<>();
1108 if (typeBuilder == null) {
1109 throw new IllegalArgumentException("Generated Type Builder cannot be NULL!");
1112 if (genTOBuilder != null) {
1113 final GeneratedTransferObject genTO = genTOBuilder.toInstance();
1114 constructGetter(typeBuilder, genTO.getName(), "Returns Primary Key of Yang List Type", genTO);
1115 genTypes.add(genTO);
1117 genTypes.add(typeBuilder.toInstance());
1125 private GeneratedTOBuilder resolveListKey(final String packageName, final ListSchemaNode list) {
1126 final String listName = list.getQName().getLocalName() + "Key";
1127 return schemaNodeToTransferObjectBuilder(packageName, list, listName);
1130 private boolean isPartOfListKey(final LeafSchemaNode leaf, final List<String> keys) {
1131 if ((leaf != null) && (keys != null) && (leaf.getQName() != null)) {
1132 final String leafName = leaf.getQName().getLocalName();
1133 if (keys.contains(leafName)) {
1140 private List<String> listKeys(final ListSchemaNode list) {
1141 final List<String> listKeys = new ArrayList<>();
1143 if (list.getKeyDefinition() != null) {
1144 final List<QName> keyDefinitions = list.getKeyDefinition();
1146 for (final QName keyDefinition : keyDefinitions) {
1147 listKeys.add(keyDefinition.getLocalName());
1153 private GeneratedTypeBuilder resolveListTypeBuilder(final String packageName, final ListSchemaNode list) {
1154 if (packageName == null) {
1155 throw new IllegalArgumentException("Package Name for Generated Type cannot be NULL!");
1158 throw new IllegalArgumentException("List Schema Node cannot be NULL!");
1161 final String schemaNodeName = list.getQName().getLocalName();
1162 final String genTypeName = parseToClassName(schemaNodeName);
1164 GeneratedTypeBuilder typeBuilder = null;
1165 final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
1166 if (builders != null) {
1167 typeBuilder = builders.get(genTypeName);
1169 if (typeBuilder == null) {
1170 typeBuilder = addDefaultInterfaceDefinition(packageName, list);
1175 private GeneratedTOBuilder resolveListKeyTOBuilder(final String packageName, final ListSchemaNode list,
1176 final List<String> listKeys) {
1177 GeneratedTOBuilder genTOBuilder = null;
1178 if (listKeys.size() > 0) {
1179 genTOBuilder = resolveListKey(packageName, list);
1181 return genTOBuilder;
1184 private GeneratedTOBuilder addEnclosedTOToTypeBuilder(TypeDefinition<?> typeDef, GeneratedTypeBuilder typeBuilder,
1186 String className = parseToClassName(leafName);
1187 GeneratedTOBuilder genTOBuilder = null;
1188 if (typeDef instanceof UnionType) {
1189 genTOBuilder = ((TypeProviderImpl) typeProvider).addUnionGeneratedTypeDefinition(
1190 typeBuilder.getFullyQualifiedName(), typeDef, className);
1191 } else if (typeDef instanceof BitsTypeDefinition) {
1192 genTOBuilder = ((TypeProviderImpl) typeProvider).bitsTypedefToTransferObject(
1193 typeBuilder.getFullyQualifiedName(), typeDef, className);
1195 if (genTOBuilder != null) {
1196 typeBuilder.addEnclosingTransferObject(genTOBuilder);
1197 return genTOBuilder;