private static void decodeConstructedOf(ParseContext pctx) {
        ThreadContext ctx = pctx.getCtx();
        Definition definition = pctx.getDefinition();
        ErrorCollector collector = pctx.getCollector();
        Ruby runtime = ctx.getRuntime();
        String name = determineName(definition.getName().orNull());
        RubyClass type = definition.getTypeAsClass(ctx)
                         .orCollectAndThrow(Errors.newASN1Error(runtime, "'type missing in ASN.1 definition"), collector);
        String tagging = definition.getTagging().orNull();
        Asn1Template template = pctx.getTemplate();
        Asn1Object object = template.getObject();
        Header h = object.getHeader();
        byte[] bytes;

        if (tagging != null && tagging.equals("EXPLICIT"))
            bytes = skipExplicitHeader(object);
        else
            bytes = object.getValue();
        
        InputStream in = new ByteArrayInputStream(bytes);
        RubyArray values;
        
        try {
            if (type.hasModuleInHierarchy(RubyTemplate.mTemplate))
                values = decodeConstructedOfTemplates(ctx, type, in);
            else
                values = decodeConstructedOfPrimitives(ctx, type, in);
        } catch (RuntimeException e) {
            throw collector.addAndReturn(Errors.newASN1Error(runtime, e.getMessage()));
        }
        
        if (values.isEmpty() && !definition.isOptional(ctx)) {
                throw collector.addAndReturn(Errors.newASN1Error(runtime, "Mandatory value " + name + "could not be parsed. Sequence is empty"));
        }
        
        if (h.getLength().isInfiniteLength()) {
            parseEoc(runtime, in);
        }
        if (!Streams.isConsumed(in)) {
            throw collector.addAndReturn(Errors.newASN1Error(runtime, "Data left that could not be parsed"));
        }

        template.setValue(values);
        /* invalidate cached encoding */
        object.invalidateValue();
        template.setDecoded(true);
    }