+ public <K, KT extends K, N extends StatementNamespace<K, ?, ?>> void addContext(final Class<N> namespace,
+ final KT key,final StmtContext<?, ?, ?> stmt) {
+ addContextToNamespace(namespace, key, stmt);
+ }
+
+ @Override
+ public <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>> Mutable<X, Y, Z> childCopyOf(
+ final StmtContext<X, Y, Z> stmt, final CopyType type, final QNameModule targetModule) {
+ Preconditions.checkState(stmt.getCompletedPhase() == ModelProcessingPhase.EFFECTIVE_MODEL,
+ "Attempted to copy statement %s which has completed phase %s", stmt, stmt.getCompletedPhase());
+
+ Preconditions.checkArgument(stmt instanceof SubstatementContext, "Unsupported statement %s", stmt);
+
+ final SubstatementContext<X, Y, Z> original = (SubstatementContext<X, Y, Z>)stmt;
+ final SubstatementContext<X, Y, Z> copy = new SubstatementContext<>(original, this, type, targetModule);
+
+ original.definition().onStatementAdded(copy);
+ original.copyTo(copy, type, targetModule);
+
+ return copy;
+ }
+
+ final void copyTo(final StatementContextBase<?, ?, ?> target, final CopyType typeOfCopy,
+ @Nullable final QNameModule targetModule) {
+ final Collection<Mutable<?, ?, ?>> buffer = new ArrayList<>(substatements.size() + effective.size());
+
+ for (final Mutable<?, ?, ?> stmtContext : substatements.values()) {
+ if (stmtContext.isSupportedByFeatures()) {
+ copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
+ }
+ }
+
+ for (final Mutable<?, ?, ?> stmtContext : effective) {
+ copySubstatement(stmtContext, target, typeOfCopy, targetModule, buffer);
+ }
+
+ target.addEffectiveSubstatements(buffer);
+ }
+
+ private void copySubstatement(final Mutable<?, ?, ?> stmtContext, final Mutable<?, ?, ?> target,
+ final CopyType typeOfCopy, final QNameModule newQNameModule, final Collection<Mutable<?, ?, ?>> buffer) {
+ if (needToCopyByUses(stmtContext)) {
+ final Mutable<?, ?, ?> copy = target.childCopyOf(stmtContext, typeOfCopy, newQNameModule);
+ 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());
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(MoreObjects.toStringHelper(this).omitNullValues()).toString();
+ }
+
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("definition", definition).add("rawArgument", rawArgument);