class StringAggStateType extends DataType<StringAggState> implements Streamer<StringAggState> {

        static final StringAggStateType INSTANCE = new StringAggStateType();

        @Override
        public int id() {
            return 1025;
        }

        @Override
        public Precedence precedence() {
            return Precedence.CUSTOM;
        }

        @Override
        public String getName() {
            return "string_list";
        }

        @Override
        public Streamer<StringAggState> streamer() {
            return this;
        }

        @Override
        public StringAggState sanitizeValue(Object value) {
            return (StringAggState) value;
        }

        @Override
        public int compare(StringAggState val1, StringAggState val2) {
            return 0;
        }

        @Override
        public StringAggState readValueFrom(StreamInput in) throws IOException {
            return new StringAggState(in);
        }

        @Override
        public void writeValueTo(StreamOutput out, StringAggState val) throws IOException {
            val.writeTo(out);
        }

        @Override
        public long valueBytes(StringAggState value) {
            throw new UnsupportedOperationException("valueSize is not implemented for StringAggStateType");
        }
    }

    private final Signature signature;
    private final BoundSignature boundSignature;

    public StringAgg(Signature signature, BoundSignature boundSignature) {
        this.signature = signature;
        this.boundSignature = boundSignature;
    }

    @Override
    public StringAggState newState(RamAccounting ramAccounting,
                                   Version indexVersionCreated,
                                   Version minNodeInCluster,
                                   MemoryManager memoryManager) {
        return new StringAggState();
    }

    @Override
    public StringAggState iterate(RamAccounting ramAccounting,
                                  MemoryManager memoryManager,
                                  StringAggState state,
                                  Input<?>... args) throws CircuitBreakingException {
        String expression = (String) args[0].value();
        if (expression == null) {
            return state;
        }
        ramAccounting.addBytes(LIST_ENTRY_OVERHEAD + RamUsageEstimator.sizeOf(expression));
        String delimiter = (String) args[1].value();
        if (delimiter != null) {
            if (state.firstDelimiter == null && state.values.isEmpty()) {
                state.firstDelimiter = delimiter;
            } else {
                ramAccounting.addBytes(LIST_ENTRY_OVERHEAD + RamUsageEstimator.sizeOf(delimiter));
                state.values.add(delimiter);
            }
        }
        state.values.add(expression);
        return state;
    }

    @Override
    public boolean isRemovableCumulative() {
        return true;
    }

    @Override
    public StringAggState removeFromAggregatedState(RamAccounting ramAccounting,
                                                    StringAggState previousAggState,
                                                    Input<?>[]stateToRemove) {<FILL_FUNCTION_BODY>

        String expression = (String) stateToRemove[0].value();
        if (expression == null) {
            return previousAggState;
        }
        String delimiter = (String) stateToRemove[1].value();

        int indexOfExpression = previousAggState.values.indexOf(expression);
        if (indexOfExpression > -1) {
            ramAccounting.addBytes(-LIST_ENTRY_OVERHEAD + RamUsageEstimator.sizeOf(expression));
            if (delimiter != null) {
                String elementNextToExpression = previousAggState.values.get(indexOfExpression + 1);
                if (elementNextToExpression.equalsIgnoreCase(delimiter)) {
                    previousAggState.values.remove(indexOfExpression + 1);
                }
            }
            previousAggState.values.remove(indexOfExpression);
        }
        return previousAggState;
    
<methods>public non-sealed void <init>() ,public DocValueAggregator<?> getDocValueAggregator(io.crate.expression.reference.doc.lucene.LuceneReferenceResolver, List<io.crate.metadata.Reference>, io.crate.metadata.doc.DocTableInfo, List<Literal<?>>) ,public boolean isRemovableCumulative() ,public transient abstract io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState iterate(io.crate.data.breaker.RamAccounting, io.crate.memory.MemoryManager, io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState, Input<?>[]) throws org.elasticsearch.common.breaker.CircuitBreakingException,public abstract io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState newState(io.crate.data.breaker.RamAccounting, org.elasticsearch.Version, org.elasticsearch.Version, io.crate.memory.MemoryManager) ,public AggregationFunction<?,java.lang.String> optimizeForExecutionAsWindowFunction() ,public abstract DataType<?> partialType() ,public abstract io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState reduce(io.crate.data.breaker.RamAccounting, io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState, io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState) ,public io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState removeFromAggregatedState(io.crate.data.breaker.RamAccounting, io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState, Input<?>[]) ,public abstract java.lang.String terminatePartial(io.crate.data.breaker.RamAccounting, io.crate.execution.engine.aggregation.impl.StringAgg.StringAggState) <variables>