class ImmutableReceiverChainResolutionStrategy implements IResolveDependencyStrategy {

    @Override
    public <T> T resolve(final Object... args) throws ResolveDependencyStrategyException {
        try {
            Object chainId = args[CHAIN_ID_ARG_INDEX];
            IObject description = (IObject) args[DESCRIPTION_ARG_INDEX];
            IChainStorage chainStorage = (IChainStorage) args[STORAGE_ARG_INDEX];
            IRouter router = (IRouter) args[ROUTER_ARG_INDEX];

            IKey fieldNameKey = Keys.getOrAdd("info.smart_tools.smartactors.iobject.ifield_name.IFieldName");
            IKey receiverIdKey = Keys.getOrAdd("receiver_id_from_iobject");
            IKey chainIdKey = Keys.getOrAdd("chain_id");

            IFieldName stepsFieldName = IOC.resolve(fieldNameKey, "steps");
            IFieldName exceptionalChainsFieldName = IOC.resolve(fieldNameKey, "exceptional");
            IFieldName exceptionClassFieldName = IOC.resolve(fieldNameKey, "class");
            IFieldName exceptionChainFieldName = IOC.resolve(fieldNameKey, "chain");
            IFieldName exceptionAfterFieldName = IOC.resolve(fieldNameKey, "after");

            List chainSteps = (List) description.getValue(stepsFieldName);
            List exceptionalChains = (List) description.getValue(exceptionalChainsFieldName);

            IMessageReceiver[] receivers = new IMessageReceiver[chainSteps.size()];
            IObject[] arguments = new IObject[chainSteps.size()];

            for (int i = 0; i < chainSteps.size(); i++) {
                IObject step = (IObject) chainSteps.get(i);

                receivers[i] = router.route(IOC.resolve(receiverIdKey, step));
                arguments[i] = step;
            }

            LinkedHashMap<Class<? extends Throwable>, IObject> exceptionalChainsMap = new LinkedHashMap<>();

            for (Object chainDesc : exceptionalChains) {
                IObject desc = (IObject) chainDesc;

                Class<?> clazz = this.getClass().getClassLoader().loadClass(String.valueOf(desc.getValue(exceptionClassFieldName)));
                IReceiverChain chain = chainStorage.resolve(IOC.resolve(chainIdKey, desc.getValue(exceptionChainFieldName)));
                IAction<IMessageProcessingSequence> afterExceptionAction = IOC.resolve(
                        IOC.resolve(IOC.getKeyForKeyStorage(), "afterExceptionAction#" + desc.getValue(exceptionAfterFieldName))
                );
                IObject chainAndEnv = IOC.resolve(IOC.resolve(IOC.getKeyForKeyStorage(), "info.smart_tools.smartactors.iobject.iobject.IObject"));
                chainAndEnv.setValue(exceptionChainFieldName, chain);
                chainAndEnv.setValue(exceptionAfterFieldName, afterExceptionAction);
                exceptionalChainsMap.put((Class<? extends Throwable>) clazz, chainAndEnv);
            }

            return (T) new ImmutableReceiverChain(String.valueOf(chainId), description, receivers, arguments, exceptionalChainsMap);
        } catch (ChainNotFoundException | ClassNotFoundException | ResolutionException | ReadValueException |
                RouteNotFoundException | ChangeValueException | InvalidArgumentException e) {
            throw new ResolveDependencyStrategyException(e);
        }
    }

}