@Override
    public void onFullDefinitionDeclared(
        final StmtContext.Mutable<QName, UsesStatement, EffectiveStatement<QName, UsesStatement>>
            usesNode)
        throws SourceException {

      if (StmtContextUtils.isInExtensionBody(usesNode)) {
        return;
      }

      ModelActionBuilder usesAction = usesNode.newInferenceAction(FULL_DECLARATION);
      final QName groupingName = usesNode.getStatementArgument();

      final Prerequisite<StmtContext<?, ?, ?>> sourceGroupingPre =
          usesAction.requiresCtx(usesNode, GroupingNamespace.class, groupingName, FULL_DECLARATION);
      final Prerequisite<? extends StmtContext.Mutable<?, ?, ?>> targetNodePre =
          usesAction.mutatesCtx(usesNode.getParentContext(), FULL_DECLARATION);

      usesAction.apply(
          new InferenceAction() {

            @Override
            public void apply() throws InferenceException {
              StatementContextBase<?, ?, ?> targetNodeStmtCtx =
                  (StatementContextBase<?, ?, ?>) targetNodePre.get();
              StatementContextBase<?, ?, ?> sourceGrpStmtCtx =
                  (StatementContextBase<?, ?, ?>) sourceGroupingPre.get();

              try {
                GroupingUtils.copyFromSourceToTarget(sourceGrpStmtCtx, targetNodeStmtCtx, usesNode);
                GroupingUtils.resolveUsesNode(usesNode, targetNodeStmtCtx);
              } catch (SourceException e) {
                LOG.warn(e.getMessage(), e);
                throw e;
              }
            }

            @Override
            public void prerequisiteFailed(Collection<? extends Prerequisite<?>> failed)
                throws InferenceException {
              if (failed.contains(sourceGroupingPre)) {
                throw new InferenceException(
                    "Grouping " + groupingName + " was not resolved.",
                    usesNode.getStatementSourceReference());
              }
              throw new InferenceException(
                  "Unknown error occurred.", usesNode.getStatementSourceReference());
            }
          });
    }
    @Override
    public void onStatementDefinitionDeclared(
        final Mutable<QName, BaseStatement, EffectiveStatement<QName, BaseStatement>> baseStmtCtx) {
      final Mutable<?, ?, ?> baseParentCtx = baseStmtCtx.getParentContext();
      if (StmtContextUtils.producesDeclared(baseParentCtx, IdentityStatement.class)) {

        final QName baseIdentityQName = baseStmtCtx.getStatementArgument();
        ModelActionBuilder baseIdentityAction =
            baseStmtCtx.newInferenceAction(ModelProcessingPhase.STATEMENT_DEFINITION);
        final Prerequisite<StmtContext<?, ?, ?>> requiresPrereq =
            baseIdentityAction.requiresCtx(
                baseStmtCtx,
                IdentityNamespace.class,
                baseIdentityQName,
                ModelProcessingPhase.STATEMENT_DEFINITION);
        final Prerequisite<StmtContext.Mutable<?, ?, ?>> mutatesPrereq =
            baseIdentityAction.mutatesCtx(baseParentCtx, ModelProcessingPhase.STATEMENT_DEFINITION);

        baseIdentityAction.apply(
            new InferenceAction() {
              @Override
              public void apply() throws InferenceException {
                List<StmtContext<?, ?, ?>> derivedIdentities =
                    baseStmtCtx.getFromNamespace(
                        DerivedIdentitiesNamespace.class, baseStmtCtx.getStatementArgument());
                if (derivedIdentities == null) {
                  derivedIdentities = new ArrayList<>();
                  baseStmtCtx.addToNs(
                      DerivedIdentitiesNamespace.class, baseIdentityQName, derivedIdentities);
                }
                derivedIdentities.add(baseParentCtx);
              }

              @Override
              public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
                throw new InferenceException(
                    "Unable to resolve identity "
                        + baseParentCtx.getStatementArgument()
                        + " and base identity "
                        + baseStmtCtx.getStatementArgument(),
                    baseStmtCtx.getStatementSourceReference());
              }
            });
      }
    }
  private void initCopyType(
      StmtContext<QName, OutputStatement, EffectiveStatement<QName, OutputStatement>> ctx) {

    Set<TypeOfCopy> copyTypesFromOriginal = StmtContextUtils.getCopyTypesFromOriginal(ctx);

    if (copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_AUGMENTATION)) {
      augmenting = true;
    }
    if (copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_USES)) {
      addedByUses = true;
    }
    if (copyTypesFromOriginal.contains(TypeOfCopy.ADDED_BY_USES_AUGMENTATION)) {
      addedByUses = augmenting = true;
    }

    if (ctx.getTypeOfCopy() != TypeOfCopy.ORIGINAL) {
      original = (ContainerSchemaNode) ctx.getOriginalCtx().buildEffective();
    }
  }