+ private void copyStatements(final SubstatementContext<A, D, E> original, final QNameModule newQNameModule,
+ final CopyType typeOfCopy) {
+ final Collection<? extends Mutable<?, ?, ?>> declared = original.mutableDeclaredSubstatements();
+ final Collection<? extends Mutable<?, ?, ?>> effective = original.mutableEffectiveSubstatements();
+ final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(declared.size() + effective.size());
+
+ for (final Mutable<?, ?, ?> stmtContext : declared) {
+ if (stmtContext.isSupportedByFeatures()) {
+ copySubstatement(stmtContext, newQNameModule, typeOfCopy, buffer);
+ }
+ }
+
+ for (final Mutable<?, ?, ?> stmtContext : effective) {
+ copySubstatement(stmtContext, newQNameModule, typeOfCopy, buffer);
+ }
+
+ addEffectiveSubstatements(buffer);
+ }
+
+ private void copySubstatement(final Mutable<?, ?, ?> stmtContext, final QNameModule newQNameModule,
+ final CopyType typeOfCopy, final Collection<Mutable<?, ?, ?>> buffer) {
+ if (needToCopyByUses(stmtContext)) {
+ final Mutable<?, ?, ?> copy = stmtContext.createCopy(newQNameModule, this, typeOfCopy);
+ LOG.debug("Copying substatement {} for {} as", stmtContext, this, copy);
+ buffer.add(copy);
+ } else if (isReusedByUses(stmtContext)) {
+ LOG.debug("Reusing substatement {} for {}", stmtContext, this);
+ buffer.add(stmtContext);
+ } else {
+ LOG.debug("Skipping statement {}", stmtContext);
+ }
+ }
+
+ // FIXME: revise this, as it seems to be wrong
+ private static final Set<YangStmtMapping> NOCOPY_FROM_GROUPING_SET = ImmutableSet.of(
+ YangStmtMapping.DESCRIPTION,
+ YangStmtMapping.REFERENCE,
+ YangStmtMapping.STATUS);
+ private static final Set<YangStmtMapping> REUSED_DEF_SET = ImmutableSet.of(
+ YangStmtMapping.TYPE,
+ YangStmtMapping.TYPEDEF,
+ YangStmtMapping.USES);
+
+ private static boolean needToCopyByUses(final StmtContext<?, ?, ?> stmtContext) {
+ final StatementDefinition def = stmtContext.getPublicDefinition();
+ if (REUSED_DEF_SET.contains(def)) {
+ LOG.debug("Will reuse {} statement {}", def, stmtContext);
+ return false;
+ }
+ if (NOCOPY_FROM_GROUPING_SET.contains(def)) {
+ return !YangStmtMapping.GROUPING.equals(stmtContext.getParentContext().getPublicDefinition());
+ }
+
+ LOG.debug("Will copy {} statement {}", def, stmtContext);
+ return true;
+ }
+
+ private static boolean isReusedByUses(final StmtContext<?, ?, ?> stmtContext) {
+ return REUSED_DEF_SET.contains(stmtContext.getPublicDefinition());
+ }
+
+ private boolean isSupportedAsShorthandCase() {
+ final Collection<?> supportedCaseShorthands = getFromNamespace(ValidationBundlesNamespace.class,
+ ValidationBundleType.SUPPORTED_CASE_SHORTHANDS);
+ return supportedCaseShorthands == null || supportedCaseShorthands.contains(getPublicDefinition());
+ }
+
+ private SchemaPath createSchemaPath() {
+ final Optional<SchemaPath> maybeParentPath = parent.getSchemaPath();
+ Verify.verify(maybeParentPath.isPresent(), "Parent %s does not have a SchemaPath", parent);
+ final SchemaPath parentPath = maybeParentPath.get();
+
+ if (StmtContextUtils.isUnknownNode(this)) {
+ return parentPath.createChild(getPublicDefinition().getStatementName());
+ }
+ if (argument instanceof QName) {
+ final QName qname = (QName) argument;
+ if (StmtContextUtils.producesDeclared(this, UsesStatement.class)) {
+ return maybeParentPath.orNull();
+ }
+
+ final SchemaPath path;
+ if ((StmtContextUtils.producesDeclared(getParentContext(), ChoiceStatement.class)
+ || Boolean.TRUE.equals(parent.getFromNamespace(AugmentToChoiceNamespace.class, parent)))
+ && isSupportedAsShorthandCase()) {
+ path = parentPath.createChild(qname);
+ } else {
+ path = parentPath;
+ }
+ return path.createChild(qname);
+ }
+ if (argument instanceof String) {
+ // FIXME: This may yield illegal argument exceptions
+ final StmtContext<?, ?, ?> originalCtx = getOriginalCtx();
+ final QName qname = originalCtx != null ? StmtContextUtils.qnameFromArgument(originalCtx, (String) argument)
+ : StmtContextUtils.qnameFromArgument(this, (String) argument);
+ return parentPath.createChild(qname);
+ }
+ if (argument instanceof SchemaNodeIdentifier
+ && (StmtContextUtils.producesDeclared(this, AugmentStatement.class) || StmtContextUtils
+ .producesDeclared(this, RefineStatement.class) || StmtContextUtils
+ .producesDeclared(this, DeviationStatement.class))) {
+
+ return parentPath.createChild(((SchemaNodeIdentifier) argument).getPathFromRoot());
+ }
+
+ // FIXME: this does not look right
+ return maybeParentPath.orNull();