text:
package org.elasticsearch.xpack.unsignedlong;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.exc.InputCoercionException;

import org.apache.lucene.document.Field;
import org.apache.lucene.document.LongPoint;
import org.apache.lucene.document.SortedNumericDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.sandbox.search.IndexSortSortedNumericDocValuesRangeQuery;
import org.apache.lucene.search.IndexOrDocValuesQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.Explicit;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
import org.elasticsearch.index.fielddata.plain.SortedNumericIndexFieldData;
import org.elasticsearch.index.mapper.DocumentParserContext;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperBuilderContext;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.SimpleMappedFieldType;
import org.elasticsearch.index.mapper.SourceValueFetcher;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.mapper.TimeSeriesIdFieldMapper;
import org.elasticsearch.index.mapper.TimeSeriesParams;
import org.elasticsearch.index.mapper.TimeSeriesParams.MetricType;
import org.elasticsearch.index.mapper.ValueFetcher;
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.xcontent.XContentParser;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

import static org.elasticsearch.xpack.unsignedlong.UnsignedLongLeafFieldData.convertUnsignedLongToDouble;

public class UnsignedLongFieldMapper extends FieldMapper {
    public static final String CONTENT_TYPE = "unsigned_long";

    private static final long MASK_2_63 = 0x8000000000000000L;
    static final BigInteger BIGINTEGER_2_64_MINUS_ONE = BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE); // 2^64 -1
    private static final BigDecimal BIGDECIMAL_2_64_MINUS_ONE = new BigDecimal(BIGINTEGER_2_64_MINUS_ONE);

    private static UnsignedLongFieldMapper toType(FieldMapper in) {
        return (UnsignedLongFieldMapper) in;
    }

    public static class Builder extends FieldMapper.Builder {
        private final Parameter<Boolean> indexed = Parameter.indexParam(m -> toType(m).indexed, true);
        private final Parameter<Boolean> hasDocValues = Parameter.docValuesParam(m -> toType(m).hasDocValues, true);
        private final Parameter<Boolean> stored = Parameter.storeParam(m -> toType(m).stored, false);
        private final Parameter<Explicit<Boolean>> ignoreMalformed;
        private final Parameter<String> nullValue;
        private final Parameter<Map<String, String>> meta = Parameter.metaParam();

        /**
         * Parameter that marks this field as a time series dimension.
         */
        private final Parameter<Boolean> dimension;

        /**
         * Parameter that marks this field as a time series metric defining its time series metric type.
         * For the numeric fields gauge and counter metric types are
         * supported
         */
        private final Parameter<MetricType> metric;

        public Builder(String name, Settings settings) {
            this(name, IGNORE_MALFORMED_SETTING.get(settings));
        }

        public Builder(String name, boolean ignoreMalformedByDefault) {
            super(name);
            this.ignoreMalformed = Parameter.explicitBoolParam(
                "ignore_malformed",
                true,
                m -> toType(m).ignoreMalformed,
                ignoreMalformedByDefault
            );
            this.nullValue = new Parameter<>(
                "null_value",
                false,
                () -> null,
                (n, c, o) -> parseNullValueAsString(o),
                m -> toType(m).nullValue
            ).acceptsNull();

            this.dimension = TimeSeriesParams.dimensionParam(m -> toType(m).dimension).addValidator(v -> {
                if (v && (indexed.getValue() == false || hasDocValues.getValue() == false)) {
                    throw new IllegalArgumentException(
                        "Field ["
                            + TimeSeriesParams.TIME_SERIES_DIMENSION_PARAM
                            + "] requires that ["
                            + indexed.name
                            + "] and ["
                            + hasDocValues.name
                            + "] are true"
                    );
                }
            });

            this.metric = TimeSeriesParams.metricParam(m -> toType(m).metricType, MetricType.gauge, MetricType.counter).addValidator(v -> {
                if (v != null && hasDocValues.getValue() == false) {
                    throw new IllegalArgumentException(
                        "Field [" + TimeSeriesParams.TIME_SERIES_METRIC_PARAM + "] requires that [" + hasDocValues.name + "] is true"
                    );
                }
            }).precludesParameters(dimension);
        }

        private String parseNullValueAsString(Object o) {
            if (o == null) return null;
            try {
                parseUnsignedLong(o); // confirm that null_value is a proper unsigned_long
                return (o instanceof BytesRef) ? ((BytesRef) o).utf8ToString() : o.toString();
            } catch (Exception e) {
                throw new MapperParsingException("Error parsing [null_value] on field [" + name() + "]: " + e.getMessage(), e);
            }
        }

        Builder nullValue(String nullValue) {
            this.nullValue.setValue(nullValue);
            return this;
        }

        public Builder dimension(boolean dimension) {
            this.dimension.setValue(dimension);
            return this;
        }

        public Builder metric(MetricType metric) {
            this.metric.setValue(metric);
            return this;
        }

        @Override
        protected List<Parameter<?>> getParameters() {
            return List.of(indexed, hasDocValues, stored, ignoreMalformed, nullValue, meta, dimension, metric);
        }

        Number parsedNullValue() {
            if (nullValue.getValue() == null) {
                return null;
            }
            long parsed = parseUnsignedLong(nullValue.getValue());
            return parsed >= 0 ? parsed : BigInteger.valueOf(parsed).and(BIGINTEGER_2_64_MINUS_ONE);
        }

        @Override
        public UnsignedLongFieldMapper build(MapperBuilderContext context) {
            UnsignedLongFieldType fieldType = new UnsignedLongFieldType(
                context.buildFullName(name),
                indexed.getValue(),
                stored.getValue(),
                hasDocValues.getValue(),
                parsedNullValue(),
                meta.getValue(),
                dimension.getValue(),
                metric.getValue()
            );
            return new UnsignedLongFieldMapper(name, fieldType, multiFieldsBuilder.build(this, context), copyTo.build(), this);
        }
    }

    public static final TypeParser PARSER = new TypeParser((n, c) -> new Builder(n, c.getSettings()));

    public static final class UnsignedLongFieldType extends SimpleMappedFieldType {

        private final Number nullValueFormatted;
        private final boolean isDimension;
        private final MetricType metricType;

        public UnsignedLongFieldType(
            String name,
            boolean indexed,
            boolean isStored,
            boolean hasDocValues,
            Number nullValueFormatted,
            Map<String, String> meta,
            boolean isDimension,
            MetricType metricType
        ) {
            super(name, indexed, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
            this.nullValueFormatted = nullValueFormatted;
            this.isDimension = isDimension;
            this.metricType = metricType;
        }

        public UnsignedLongFieldType(String name) {
            this(name, true, false, true, null, Collections.emptyMap(), false, null);
        }

        @Override
        public String typeName() {
            return CONTENT_TYPE;
        }

        @Override
        public Query termQuery(Object value, SearchExecutionContext context) {
            failIfNotIndexed();
            Long longValue = parseTerm(value);
            if (longValue == null) {
                return new MatchNoDocsQuery();
            }
            return LongPoint.newExactQuery(name(), unsignedToSortableSignedLong(longValue));
        }

        @Override
        public Query termsQuery(Collection<?> values, SearchExecutionContext context) {
            failIfNotIndexed();
            long[] lvalues = new long[values.size()];
            int upTo = 0;
            for (Object value : values) {
                Long longValue = parseTerm(value);
                if (longValue != null) {
                    lvalues[upTo++] = unsignedToSortableSignedLong(longValue);
                }
            }
            if (upTo == 0) {
                return new MatchNoDocsQuery();
            }
            if (upTo != lvalues.length) {
                lvalues = Arrays.copyOf(lvalues, upTo);
            }
            return LongPoint.newSetQuery(name(), lvalues);
        }

        @Override
        public Query rangeQuery(
            Object lowerTerm,
            Object upperTerm,
            boolean includeLower,
            boolean includeUpper,
            SearchExecutionContext context
        ) {
            failIfNotIndexed();
            long l = Long.MIN_VALUE;
            long u = Long.MAX_VALUE;
            if (lowerTerm != null) {
                Long lt = parseLowerRangeTerm(lowerTerm, includeLower);
                if (lt == null) return new MatchNoDocsQuery();
                l = unsignedToSortableSignedLong(lt);
            }
            if (upperTerm != null) {
                Long ut = parseUpperRangeTerm(upperTerm, includeUpper);
                if (ut == null) return new MatchNoDocsQuery();
                u = unsignedToSortableSignedLong(ut);
            }
            if (l > u) return new MatchNoDocsQuery();

            Query query = LongPoint.newRangeQuery(name(), l, u);
            if (hasDocValues()) {
                Query dvQuery = SortedNumericDocValuesField.newSlowRangeQuery(name(), l, u);
                query = new IndexOrDocValuesQuery(query, dvQuery);
                if (context.indexSortedOnField(name())) {
                    query = new IndexSortSortedNumericDocValuesRangeQuery(name(), l, u, query);
                }
            }
            return query;
        }

        @Override
        public IndexFieldData.Builder fielddataBuilder(String fullyQualifiedIndexName, Supplier<SearchLookup> searchLookup) {
            failIfNoDocValues();
            return (cache, breakerService) -> {
                final IndexNumericFieldData signedLongValues = new SortedNumericIndexFieldData.Builder(
                    name(),
                    IndexNumericFieldData.NumericType.LONG,
                    (dv, n) -> { throw new UnsupportedOperationException(); }
                ).build(cache, breakerService);
                return new UnsignedLongIndexFieldData(signedLongValues, UnsignedLongDocValuesField::new);
            };
        }

        @Override
        public ValueFetcher valueFetcher(SearchExecutionContext context, String format) {
            if (format != null) {
                throw new IllegalArgumentException("Field [" + name() + "] of type [" + typeName() + "] doesn't support formats.");
            }

            return new SourceValueFetcher(name(), context, nullValueFormatted) {
                @Override
                protected Object parseSourceValue(Object value) {
                    if (value.equals("")) {
                        return nullValueFormatted;
                    }
                    long ulValue = parseUnsignedLong(value);
                    if (ulValue >= 0) {
                        return ulValue;
                    } else {
                        return BigInteger.valueOf(ulValue).and(BIGINTEGER_2_64_MINUS_ONE);
                    }
                }
            };
        }

        @Override
        public Object valueForDisplay(Object value) {
            if (value == null) {
                return null;
            }
            return value;
        }

        @Override
        public DocValueFormat docValueFormat(String format, ZoneId timeZone) {
            checkNoTimeZone(timeZone);
            return DocValueFormat.UNSIGNED_LONG_SHIFTED;
        }

        @Override
        public Function<byte[], Number> pointReaderIfPossible() {
            if (isSearchable()) {
                // convert from the shifted value back to the original value
                return (value) -> convertUnsignedLongToDouble(LongPoint.decodeDimension(value, 0));
            }
            return null;
        }

        @Override
        public CollapseType collapseType() {
            return CollapseType.NUMERIC;
        }

        /**
         * Parses value to unsigned long for Term Query
         * @param value to to parse
         * @return parsed value, if a value represents an unsigned long in the range [0, 18446744073709551615]
         *         null, if a value represents some other number
         *         throws an exception if a value is wrongly formatted number
         */
        protected static Long parseTerm(Object value) {
            if (value instanceof Number) {
                if ((value instanceof Long) || (value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
                    long lv = ((Number) value).longValue();
                    if (lv >= 0) {
                        return lv;
                    }
                } else if (value instanceof BigInteger) {
                    BigInteger bigIntegerValue = (BigInteger) value;
                    if (bigIntegerValue.compareTo(BigInteger.ZERO) >= 0 && bigIntegerValue.compareTo(BIGINTEGER_2_64_MINUS_ONE) <= 0) {
                        return bigIntegerValue.longValue();
                    }
                }
            } else {
                String stringValue = (value instanceof BytesRef) ? ((BytesRef) value).utf8ToString() : value.toString();
                try {
                    return Long.parseUnsignedLong(stringValue);
                } catch (NumberFormatException e) {
                    // try again in case a number was negative or contained decimal
                    Double.parseDouble(stringValue); // throws an exception if it is an improper number
                }
            }
            return null; // any other number: decimal or beyond the range of unsigned long
        }

        /**
         * Parses a lower term for a range query
         * @param value to parse
         * @param include whether a value should be included
         * @return parsed value to long considering include parameter
         *      0, if value is less than 0
         *      a value truncated to long, if value is in range [0, 18446744073709551615]
         *      null, if value is higher than the maximum allowed value for unsigned long
         *      throws an exception is value represents wrongly formatted number
         */
        protected static Long parseLowerRangeTerm(Object value, boolean include) {
            if ((value instanceof Long) || (value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
                long longValue = ((Number) value).longValue();
                if (longValue < 0) return 0L; // limit lowerTerm to min value for unsigned long: 0
                if (include == false) { // start from the next value
                    // for unsigned long, the next value for Long.MAX_VALUE is -9223372036854775808L
                    longValue = longValue == Long.MAX_VALUE ? Long.MIN_VALUE : ++longValue;
                }
                return longValue;
            }
            String stringValue = (value instanceof BytesRef) ? ((BytesRef) value).utf8ToString() : value.toString();
            final BigDecimal bigDecimalValue = new BigDecimal(stringValue);  // throws an exception if it is an improper number
            if (bigDecimalValue.compareTo(BigDecimal.ZERO) <= 0) {
                return 0L; // for values <=0, set lowerTerm to 0
            }
            int c = bigDecimalValue.compareTo(BIGDECIMAL_2_64_MINUS_ONE);
            if (c > 0 || (c == 0 && include == false)) {
                return null; // lowerTerm is beyond maximum value
            }
            long longValue = bigDecimalValue.longValue();
            boolean hasDecimal = (bigDecimalValue.scale() > 0 && bigDecimalValue.stripTrailingZeros().scale() > 0);
            if (include == false || hasDecimal) {
                ++longValue;
            }
            return longValue;
        }

        /**
         * Parses an upper term for a range query
         * @param value to parse
         * @param include whether a value should be included
         * @return parsed value to long considering include parameter
         *      null, if value is less that 0, as value is lower than the minimum allowed value for unsigned long
         *      a value truncated to long if value is in range [0, 18446744073709551615]
         *      -1 (unsigned long of 18446744073709551615) for values greater than 18446744073709551615
         *      throws an exception is value represents wrongly formatted number
         */
        protected static Long parseUpperRangeTerm(Object value, boolean include) {
            if ((value instanceof Long) || (value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
                long longValue = ((Number) value).longValue();
                if ((longValue < 0) || (longValue == 0 && include == false)) return null; // upperTerm is below minimum
                longValue = include ? longValue : --longValue;
                return longValue;
            }
            String stringValue = (value instanceof BytesRef) ? ((BytesRef) value).utf8ToString() : value.toString();
            final BigDecimal bigDecimalValue = new BigDecimal(stringValue);  // throws an exception if it is an improper number
            int c = bigDecimalValue.compareTo(BigDecimal.ZERO);
            if (c < 0 || (c == 0 && include == false)) {
                return null; // upperTerm is below minimum
            }
            if (bigDecimalValue.compareTo(BIGDECIMAL_2_64_MINUS_ONE) > 0) {
                return -1L; // limit upperTerm to max value for unsigned long: 18446744073709551615
            }
            long longValue = bigDecimalValue.longValue();
            boolean hasDecimal = (bigDecimalValue.scale() > 0 && bigDecimalValue.stripTrailingZeros().scale() > 0);
            if (include == false && hasDecimal == false) {
                --longValue;
            }
            return longValue;
        }

        /**
         * @return true if field has been marked as a dimension field
         */
        public boolean isDimension() {
            return isDimension;
        }

        /**
         * If field is a time series metric field, returns its metric type
         * @return the metric type or null
         */
        public MetricType getMetricType() {
            return metricType;
        }
    }

    private final boolean indexed;
    private final boolean hasDocValues;
    private final boolean stored;
    private final Explicit<Boolean> ignoreMalformed;
    private final boolean ignoreMalformedByDefault;
    private final String nullValue;
    private final Long nullValueIndexed; // null value to use for indexing, represented as shifted to signed long range
    private final boolean dimension;
    private final MetricType metricType;

    private UnsignedLongFieldMapper(
        String simpleName,
        MappedFieldType mappedFieldType,
        MultiFields multiFields,
        CopyTo copyTo,
        Builder builder
    ) {
        super(simpleName, mappedFieldType, multiFields, copyTo);
        this.indexed = builder.indexed.getValue();
        this.hasDocValues = builder.hasDocValues.getValue();
        this.stored = builder.stored.getValue();
        this.ignoreMalformed = builder.ignoreMalformed.getValue();
        this.ignoreMalformedByDefault = builder.ignoreMalformed.getDefaultValue().value();
        this.nullValue = builder.nullValue.getValue();
        if (nullValue == null) {
            this.nullValueIndexed = null;
        } else {
            long parsed = parseUnsignedLong(nullValue);
            this.nullValueIndexed = unsignedToSortableSignedLong(parsed);
        }
        this.dimension = builder.dimension.getValue();
        this.metricType = builder.metric.getValue();
    }

    boolean ignoreMalformed() {
        return ignoreMalformed.value();
    }

    @Override
    public UnsignedLongFieldType fieldType() {
        return (UnsignedLongFieldType) super.fieldType();
    }

    @Override
    protected String contentType() {
        return CONTENT_TYPE;
    }

    @Override
    protected void parseCreateField(DocumentParserContext context) throws IOException {
        XContentParser parser = context.parser();
        Long numericValue;
        if (parser.currentToken() == XContentParser.Token.VALUE_NULL) {
            numericValue = null;
        } else if (parser.currentToken() == XContentParser.Token.VALUE_STRING && parser.textLength() == 0) {
            numericValue = null;
        } else {
            try {
                if (parser.currentToken() == XContentParser.Token.VALUE_NUMBER) {
                    numericValue = parseUnsignedLong(parser.numberValue());
                } else {
                    numericValue = parseUnsignedLong(parser.text());
                }
            } catch (InputCoercionException | IllegalArgumentException | JsonParseException e) {
                if (ignoreMalformed.value() && parser.currentToken().isValue()) {
                    context.addIgnoredField(mappedFieldType.name());
                    return;
                } else {
                    throw e;
                }
            }
        }
        boolean isNullValue = false;
        if (numericValue == null) {
            numericValue = nullValueIndexed;
            if (numericValue == null) return;
            isNullValue = true;
        } else {
            numericValue = unsignedToSortableSignedLong(numericValue);
        }

        if (dimension && numericValue != null) {
            // We encode the tsid part of the dimension field. However, there is no point
            // in encoding the tsid value if we do not generate the _tsid field.
            BytesReference bytes = context.getMetadataMapper(TimeSeriesIdFieldMapper.NAME) != null
                ? TimeSeriesIdFieldMapper.encodeTsidUnsignedLongValue(numericValue)
                : null;
            context.doc().addDimensionBytes(fieldType().name(), bytes);
        }

        List<Field> fields = new ArrayList<>();
        if (indexed) {
            fields.add(new LongPoint(fieldType().name(), numericValue));
        }
        if (hasDocValues) {
            fields.add(new SortedNumericDocValuesField(fieldType().name(), numericValue));
        }
        if (stored) {
            // for stored field, keeping original unsigned_long value in the String form
            String storedValued = isNullValue ? nullValue : Long.toUnsignedString(unsignedToSortableSignedLong(numericValue));
            fields.add(new StoredField(fieldType().name(), storedValued));
        }
        context.doc().addAll(fields);

        if (hasDocValues == false && (stored || indexed)) {
            context.addToFieldNames(fieldType().name());
        }
    }

    @Override
    public FieldMapper.Builder getMergeBuilder() {
        return new Builder(simpleName(), ignoreMalformedByDefault).dimension(dimension).metric(metricType).init(this);
    }

    /**
     * Parse object to unsigned long
     * @param value must represent an unsigned long in rage [0;18446744073709551615] or an exception will be thrown
     */
    private static long parseUnsignedLong(Object value) {
        if (value instanceof Number) {
            if ((value instanceof Long) || (value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) {
                long lv = ((Number) value).longValue();
                if (lv < 0) {
                    throw new IllegalArgumentException("Value [" + lv + "] is out of range for unsigned long.");
                }
                return lv;
            } else if (value instanceof Double || value instanceof Float) {
                final Number v = (Number) value;
                if (Double.compare(v.doubleValue(), Math.floor(v.doubleValue())) != 0) {
                    throw new IllegalArgumentException("Value \"" + value + "\" has a decimal part");
                }
                return parseUnsignedLong(v.longValue());
            } else if (value instanceof BigInteger) {
                BigInteger bigIntegerValue = (BigInteger) value;
                if (bigIntegerValue.compareTo(BIGINTEGER_2_64_MINUS_ONE) > 0 || bigIntegerValue.compareTo(BigInteger.ZERO) < 0) {
                    throw new IllegalArgumentException("Value [" + bigIntegerValue + "] is out of range for unsigned long");
                }
                return bigIntegerValue.longValue();
            } else if (value instanceof BigDecimal) {
                return parseUnsignedLong(((BigDecimal) value).toBigIntegerExact());
            }
            // throw exception for all other numeric types with decimal parts
            throw new IllegalArgumentException("For input string: [" + value + "].");
        } else {
            final String stringValue = (value instanceof BytesRef) ? ((BytesRef) value).utf8ToString() : value.toString();
            try {
                return Long.parseUnsignedLong(stringValue);
            } catch (NumberFormatException ignored) {
                final BigInteger bigInteger;
                try {
                    final BigDecimal bigDecimal = new BigDecimal(stringValue);
                    bigInteger = bigDecimal.toBigIntegerExact();
                } catch (ArithmeticException e) {
                    throw new IllegalArgumentException("Value \"" + stringValue + "\" has a decimal part");
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("For input string: \"" + stringValue + "\"");
                }
                return parseUnsignedLong(bigInteger);
            }
        }
    }

    /**
     * Convert an unsigned long to the signed long by subtract 2^63 from it
     * @param value – unsigned long value in the range [0; 2^64-1], values greater than 2^63-1 are negative
     * @return signed long value in the range [-2^63; 2^63-1]
     */
    private static long unsignedToSortableSignedLong(long value) {
        // subtracting 2^63 or 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
        // equivalent to flipping the first bit
        return value ^ MASK_2_63;
    }

    /**
     * Convert a signed long to unsigned by adding 2^63 to it
     * @param value – signed long value in the range [-2^63; 2^63-1]
     * @return unsigned long value in the range [0; 2^64-1],  values greater then 2^63-1 are negative
     */
    protected static long sortableSignedLongToUnsigned(long value) {
        // adding 2^63 or 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
        // equivalent to flipping the first bit
        return value ^ MASK_2_63;
    }

}


text:
\hypertarget{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository}{\section{Highway.\-Data.\-Interfaces.\-I\-Async\-Repository Interface Reference}
\label{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository}\index{Highway.\-Data.\-Interfaces.\-I\-Async\-Repository@{Highway.\-Data.\-Interfaces.\-I\-Async\-Repository}}
}

The interface used to interact with the O\-R\-M Specific Implementations

Inheritance diagram for Highway.\-Data.\-Interfaces.\-I\-Async\-Repository\-:\begin{figure}[H]
\begin{center}
\leavevmode
\includegraphics[height=2.000000cm]{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository}
\end{center}
\end{figure}
\subsection*{Public Member Functions}
\begin{DoxyCompactItemize}
\item
Task$<$ I\-Enumerable$<$ T $>$ $>$ \hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_adf81905d686e44b115548921a7d6d72d}{Find$<$ T $>$} (\hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_query-g}{I\-Query}$<$ T $>$ query)
\begin{DoxyCompactList}\small\item\em Executes a prebuilt I\-Query\{\-T\} and returns an I\-Enumerable\{\-T\} \end{DoxyCompactList}\item
Task$<$ T $>$ \hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a7eed1d89c1104a467bfdc12cb0de3133}{Get$<$ T $>$} (\hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_scalar-g}{I\-Scalar}$<$ T $>$ query)
\begin{DoxyCompactList}\small\item\em Executes a prebuilt I\-Scalar\{\-T\} and returns a single instance of {\itshape T}  \end{DoxyCompactList}\item
Task \hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a5f396f5c1aa1b9e3eced829bf736a4ab}{Execute} (\hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_command}{I\-Command} command)
\begin{DoxyCompactList}\small\item\em Executes a prebuilt \hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_command}{I\-Command} \end{DoxyCompactList}\end{DoxyCompactItemize}
\subsection*{Properties}
\begin{DoxyCompactItemize}
\item
\hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_data_context}{I\-Data\-Context} \hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a03e1d3bb759c50309a4be719eca25a0f}{Context}\hspace{0.3cm}{\ttfamily  \mbox{[}get\mbox{]}}
\begin{DoxyCompactList}\small\item\em Reference to the Context the repository is using \end{DoxyCompactList}\item
\hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_event_manager}{I\-Event\-Manager} \hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_ad3c1510134e22665788e2f8eccd954f0}{Event\-Manager}\hspace{0.3cm}{\ttfamily  \mbox{[}get\mbox{]}}
\begin{DoxyCompactList}\small\item\em Reference to the Event\-Manager the repository is using \end{DoxyCompactList}\end{DoxyCompactItemize}

\subsection{Detailed Description}
The interface used to interact with the O\-R\-M Specific Implementations

\subsection{Member Function Documentation}
\hypertarget{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a5f396f5c1aa1b9e3eced829bf736a4ab}{\index{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}!Execute@{Execute}}
\index{Execute@{Execute}!Highway::Data::Interfaces::IAsyncRepository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}}
\subsubsection[{Execute}]{\setlength{\rightskip}{0pt plus 5cm}Task Highway.\-Data.\-Interfaces.\-I\-Async\-Repository.\-Execute (
\begin{DoxyParamCaption}
\item[{{\bf I\-Command}}]{command}
\end{DoxyParamCaption}
)}}\label{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a5f396f5c1aa1b9e3eced829bf736a4ab}

Executes a prebuilt \hyperlink{interface_highway_1_1_data_1_1_interfaces_1_1_i_command}{I\-Command}

\begin{DoxyParams}{Parameters}
{\em command} & The prebuilt command object\\
\hline
\end{DoxyParams}

Implemented in \hyperlink{class_highway_1_1_data_1_1_async_repository_afa774a72108c37212f0862fa61a5cec3}{Highway.\-Data.\-Async\-Repository}.

\hypertarget{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_adf81905d686e44b115548921a7d6d72d}{\index{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}!Find$<$ T $>$@{Find$<$ T $>$}}
\index{Find$<$ T $>$@{Find$<$ T $>$}!Highway::Data::Interfaces::IAsyncRepository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}}
\subsubsection[{Find$<$ T $>$}]{\setlength{\rightskip}{0pt plus 5cm}Task$<$I\-Enumerable$<$T$>$ $>$ Highway.\-Data.\-Interfaces.\-I\-Async\-Repository.\-Find$<$ T $>$ (
\begin{DoxyParamCaption}
\item[{{\bf I\-Query}$<$ T $>$}]{query}
\end{DoxyParamCaption}
)}}\label{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_adf81905d686e44b115548921a7d6d72d}

Executes a prebuilt I\-Query\{\-T\} and returns an I\-Enumerable\{\-T\}

\begin{DoxyTemplParams}{Template Parameters}
{\em T} & The Entity being queried\\
\hline
\end{DoxyTemplParams}

\begin{DoxyParams}{Parameters}
{\em query} & The prebuilt Query Object\\
\hline
\end{DoxyParams}
\begin{DoxyReturn}{Returns}
The I\-Enumerable\{\-T\} returned from the query
\end{DoxyReturn}

Implemented in \hyperlink{class_highway_1_1_data_1_1_async_repository_ad0ad809e167fb82b047270031b6bc47c}{Highway.\-Data.\-Async\-Repository}.

\begin{Desc}
\item[Type Constraints]\begin{description}
\item[{\em T} : {\em class}]\end{description}
\end{Desc}
\hypertarget{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a7eed1d89c1104a467bfdc12cb0de3133}{\index{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}!Get$<$ T $>$@{Get$<$ T $>$}}
\index{Get$<$ T $>$@{Get$<$ T $>$}!Highway::Data::Interfaces::IAsyncRepository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}}
\subsubsection[{Get$<$ T $>$}]{\setlength{\rightskip}{0pt plus 5cm}Task$<$T$>$ Highway.\-Data.\-Interfaces.\-I\-Async\-Repository.\-Get$<$ T $>$ (
\begin{DoxyParamCaption}
\item[{{\bf I\-Scalar}$<$ T $>$}]{query}
\end{DoxyParamCaption}
)}}\label{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a7eed1d89c1104a467bfdc12cb0de3133}

Executes a prebuilt I\-Scalar\{\-T\} and returns a single instance of {\itshape T}

\begin{DoxyTemplParams}{Template Parameters}
{\em T} & The Entity being queried\\
\hline
\end{DoxyTemplParams}

\begin{DoxyParams}{Parameters}
{\em query} & The prebuilt Query Object\\
\hline
\end{DoxyParams}
\begin{DoxyReturn}{Returns}
The instance of {\itshape T}  returned from the query
\end{DoxyReturn}

Implemented in \hyperlink{class_highway_1_1_data_1_1_async_repository_a0c032814b93798874cd36b30ecf821dc}{Highway.\-Data.\-Async\-Repository}.

\subsection{Property Documentation}
\hypertarget{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a03e1d3bb759c50309a4be719eca25a0f}{\index{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}!Context@{Context}}
\index{Context@{Context}!Highway::Data::Interfaces::IAsyncRepository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}}
\subsubsection[{Context}]{\setlength{\rightskip}{0pt plus 5cm}{\bf I\-Data\-Context} Highway.\-Data.\-Interfaces.\-I\-Async\-Repository.\-Context\hspace{0.3cm}{\ttfamily [get]}}}\label{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_a03e1d3bb759c50309a4be719eca25a0f}

Reference to the Context the repository is using

Implemented in \hyperlink{class_highway_1_1_data_1_1_async_repository_abfd6073ad2ad20eebaf97568c7ed8d7e}{Highway.\-Data.\-Async\-Repository}.

\hypertarget{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_ad3c1510134e22665788e2f8eccd954f0}{\index{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}!Event\-Manager@{Event\-Manager}}
\index{Event\-Manager@{Event\-Manager}!Highway::Data::Interfaces::IAsyncRepository@{Highway\-::\-Data\-::\-Interfaces\-::\-I\-Async\-Repository}}
\subsubsection[{Event\-Manager}]{\setlength{\rightskip}{0pt plus 5cm}{\bf I\-Event\-Manager} Highway.\-Data.\-Interfaces.\-I\-Async\-Repository.\-Event\-Manager\hspace{0.3cm}{\ttfamily [get]}}}\label{interface_highway_1_1_data_1_1_interfaces_1_1_i_async_repository_ad3c1510134e22665788e2f8eccd954f0}

Reference to the Event\-Manager the repository is using

Implemented in \hyperlink{class_highway_1_1_data_1_1_async_repository_ab41ad1eec675e831aba15b677d27717e}{Highway.\-Data.\-Async\-Repository}.

The documentation for this interface was generated from the following file\-:\begin{DoxyCompactItemize}
\item
Highway.\-Data/\-Interfaces/I\-Async\-Repository.\-cs\end{DoxyCompactItemize}

redpajama_set_name: RedPajamaGithub


text:
var HQNavBar = function (o) {
    var self = this;
    self.navigationTabs = ko.observableArray();
    self.navBar = o.navBar || $('#hq-navigation-bar');
    self.tabBar = self.navBar.find('ul[class="nav"]');
    self.buttonBar = self.navBar.find('div[class*="secondary-nav"]');

    self.isThereOverlap = function () {
        while( (self.tabBar.offset().left+self.tabBar.width()) > self.buttonBar.offset().left) {
            self.navigationTabs.push(self.tabBar.find('li').last());
            self.tabBar.find('li').last().remove();
        }
    };

    $(window).resize( function (data, event) {
        self.isThereOverlap();
    });
};


text:
var fs = require('fs'),
    sinon = require('sinon'),
    expect = require('chai').expect,
    IS_BROWSER = typeof window !== 'undefined';

describe('http methods', function () {
    var testrun,
        URL;

    before(function () {
        // Echo raw request message to handle custom http methods
        URL = global.servers.raw;
    });

    describe('standard (GET)', function () {
        before(function (done) {
            this.run({
                collection: {
                    item: [{
                        request: {
                            url: URL,
                            method: 'GET',
                            header: [{ key: 'Connection', value: 'close' }]
                        }
                    }]
                }
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should complete the run', function () {
            expect(testrun).to.be.ok;
            sinon.assert.calledOnce(testrun.start);
            sinon.assert.calledOnce(testrun.done);
            sinon.assert.calledWith(testrun.done.getCall(0), null);
        });

        it('should handle standard http method correctly', function () {
            sinon.assert.calledOnce(testrun.request);
            sinon.assert.calledWith(testrun.request.getCall(0), null);

            sinon.assert.calledOnce(testrun.response);
            sinon.assert.calledWith(testrun.response.getCall(0), null);

            var request = testrun.request.getCall(0).args[3],
                response = testrun.request.getCall(0).args[2].stream.toString();

            // method sent to server in request
            expect(request).to.have.property('method', 'GET');

            // method received at server
            expect(response).to.include('GET / HTTP/1.1');
        });
    });

    describe('custom (POSTMAN)', function () {
        before(function (done) {
            this.run({
                collection: {
                    item: [{
                        request: {
                            url: URL,
                            method: 'POSTMAN'
                        }
                    }]
                }
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should complete the run', function () {
            expect(testrun).to.be.ok;
            sinon.assert.calledOnce(testrun.start);
            sinon.assert.calledOnce(testrun.done);
            sinon.assert.calledWith(testrun.done.getCall(0), null);
        });

        it('should handle custom http method correctly', function () {
            sinon.assert.calledOnce(testrun.request);
            sinon.assert.calledWith(testrun.request.getCall(0), null);

            sinon.assert.calledOnce(testrun.response);
            sinon.assert.calledWith(testrun.response.getCall(0), null);

            var request = testrun.request.getCall(0).args[3],
                response = testrun.request.getCall(0).args[2].stream.toString();

            // method sent to server in request
            expect(request).to.have.property('method', 'POSTMAN');

            // method received at server
            expect(response).to.include('POSTMAN / HTTP/1.1');
        });

        describe('with request body', function () {
            describe('raw', function () {
                before(function (done) {
                    this.run({
                        collection: {
                            item: [{
                                request: {
                                    url: URL,
                                    method: 'POSTMAN',
                                    body: {
                                        mode: 'raw',
                                        raw: 'foo=bar'
                                    }
                                }
                            }]
                        }
                    }, function (err, results) {
                        testrun = results;
                        done(err);
                    });
                });

                it('should complete the run', function () {
                    expect(testrun).to.be.ok;
                    sinon.assert.calledOnce(testrun.start);
                    sinon.assert.calledOnce(testrun.done);
                    sinon.assert.calledWith(testrun.done.getCall(0), null);
                });

                it('should handle raw mode correctly', function () {
                    sinon.assert.calledOnce(testrun.request);
                    sinon.assert.calledWith(testrun.request.getCall(0), null);

                    sinon.assert.calledOnce(testrun.response);
                    sinon.assert.calledWith(testrun.response.getCall(0), null);

                    var request = testrun.request.getCall(0).args[3],
                        response = testrun.request.getCall(0).args[2].stream.toString();

                    // method sent to server in request
                    expect(request).to.have.property('method', 'POSTMAN');

                    // response received at server
                    expect(response).to.include('Content-Type: text/plain');
                    expect(response).to.include('foo=bar');
                });
            });

            (IS_BROWSER ? describe.skip : describe)('urlencoded', function () {
                before(function (done) {
                    this.run({
                        collection: {
                            item: [{
                                request: {
                                    url: URL,
                                    method: 'POSTMAN',
                                    body: {
                                        mode: 'urlencoded',
                                        urlencoded: [{
                                            key: 'foo',
                                            value: 'bar'
                                        }]
                                    }
                                }
                            }]
                        }
                    }, function (err, results) {
                        testrun = results;
                        done(err);
                    });
                });

                it('should complete the run', function () {
                    expect(testrun).to.be.ok;
                    sinon.assert.calledOnce(testrun.start);
                    sinon.assert.calledOnce(testrun.done);
                    sinon.assert.calledWith(testrun.done.getCall(0), null);
                });

                it('should handle urlencoded mode correctly', function () {
                    sinon.assert.calledOnce(testrun.request);
                    sinon.assert.calledWith(testrun.request.getCall(0), null);

                    sinon.assert.calledOnce(testrun.response);
                    sinon.assert.calledWith(testrun.response.getCall(0), null);

                    var request = testrun.request.getCall(0).args[3],
                        response = testrun.request.getCall(0).args[2].stream.toString();

                    // method sent to server in request
                    expect(request).to.have.property('method', 'POSTMAN');

                    // response received at server
                    expect(response).to.include('Content-Type: application/x-www-form-urlencoded');
                    expect(response).to.include('foo=bar');
                });
            });

            describe('formdata', function () {
                before(function (done) {
                    this.run({
                        collection: {
                            item: [{
                                request: {
                                    url: URL,
                                    method: 'POSTMAN',
                                    body: {
                                        mode: 'formdata',
                                        formdata: [{
                                            key: 'foo',
                                            value: 'bar'
                                        }]
                                    }
                                }
                            }]
                        }
                    }, function (err, results) {
                        testrun = results;
                        done(err);
                    });
                });

                it('should complete the run', function () {
                    expect(testrun).to.be.ok;
                    sinon.assert.calledOnce(testrun.start);
                    sinon.assert.calledOnce(testrun.done);
                    sinon.assert.calledWith(testrun.done.getCall(0), null);
                });

                it('should handle formdata mode correctly', function () {
                    sinon.assert.calledOnce(testrun.request);
                    sinon.assert.calledWith(testrun.request.getCall(0), null);

                    sinon.assert.calledOnce(testrun.response);
                    sinon.assert.calledWith(testrun.response.getCall(0), null);

                    var request = testrun.request.getCall(0).args[3],
                        response = testrun.request.getCall(0).args[2].stream.toString();

                    // method sent to server in request
                    expect(request).to.have.property('method', 'POSTMAN');

                    // response received at server
                    expect(response).to.include('Content-Type: multipart/form-data');
                    expect(response).to.include('name="foo"\r\n\r\nbar');
                });
            });

            (IS_BROWSER ? describe.skip : describe)('file', function () {
                // eslint-disable-next-line mocha/no-sibling-hooks
                before(function (done) {
                    this.run({
                        fileResolver: fs,
                        collection: {
                            item: [{
                                request: {
                                    url: URL,
                                    method: 'POSTMAN',
                                    body: {
                                        mode: 'file',
                                        file: {
                                            src: 'test/fixtures/upload-file.json'
                                        }
                                    }
                                }
                            }]
                        }
                    }, function (err, results) {
                        testrun = results;
                        done(err);
                    });
                });

                // eslint-disable-next-line mocha/no-identical-title
                it('should complete the run', function () {
                    expect(testrun).to.be.ok;
                    sinon.assert.calledOnce(testrun.start);
                    sinon.assert.calledOnce(testrun.done);
                    sinon.assert.calledWith(testrun.done.getCall(0), null);
                });

                it('should handle file mode correctly', function () {
                    sinon.assert.calledOnce(testrun.request);
                    sinon.assert.calledWith(testrun.request.getCall(0), null);

                    sinon.assert.calledOnce(testrun.response);
                    sinon.assert.calledWith(testrun.response.getCall(0), null);

                    var request = testrun.request.getCall(0).args[3],
                        response = testrun.request.getCall(0).args[2].stream.toString();

                    // method sent to server in request
                    expect(request).to.have.property('method', 'POSTMAN');

                    // response received at server
                    expect(response).to.include('Content-Type: application/json');
                    expect(response).to.include('{\n\t"key1":"value1",\n\t"key2": 2\n}\n');
                });
            });
        });
    });

    describe('missing', function () {
        before(function (done) {
            this.run({
                collection: {
                    item: [{
                        request: { url: URL }
                    }]
                }
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should complete the run', function () {
            expect(testrun).to.be.ok;
            sinon.assert.calledOnce(testrun.start);
            sinon.assert.calledOnce(testrun.done);
            sinon.assert.calledWith(testrun.done.getCall(0), null);
        });

        it('should defaults to GET method', function () {
            sinon.assert.calledOnce(testrun.request);
            sinon.assert.calledWith(testrun.request.getCall(0), null);

            sinon.assert.calledOnce(testrun.response);
            sinon.assert.calledWith(testrun.response.getCall(0), null);

            var request = testrun.request.getCall(0).args[3],
                response = testrun.request.getCall(0).args[2].stream.toString();

            // method sent to server in request
            expect(request).to.have.property('method', 'GET');

            // method received at server
            expect(response).to.include('GET / HTTP/1.1');
        });
    });

    describe('non-string', function () {
        before(function (done) {
            this.run({
                collection: {
                    item: [{
                        request: {
                            url: URL,
                            method: 12345
                        }
                    }]
                }
            }, function (err, results) {
                testrun = results;
                done(err);
            });
        });

        it('should complete the run', function () {
            expect(testrun).to.be.ok;
            sinon.assert.calledOnce(testrun.start);
            sinon.assert.calledOnce(testrun.done);
            sinon.assert.calledWith(testrun.done.getCall(0), null);
        });

        it('should handle non-string method correctly', function () {
            sinon.assert.calledOnce(testrun.request);
            sinon.assert.calledWith(testrun.request.getCall(0), null);

            sinon.assert.calledOnce(testrun.response);
            sinon.assert.calledWith(testrun.response.getCall(0), null);

            var request = testrun.request.getCall(0).args[3],
                response = testrun.request.getCall(0).args[2].stream.toString();

            // method sent to server in request
            expect(request).to.have.property('method', '12345');

            // method received at server
            expect(response).to.include('12345 / HTTP/1.1');
        });
    });
});


text:
[Cac2er](../../index.md) / [com.wcaokaze.cac2er](../index.md) / [WritableWeakCache](index.md) / [setContent](./set-content.md)

# setContent

`abstract fun setContent(content: `[`T`](index.md#T)`): `[`Unit`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unit/index.html) [(source)](https://github.com/wcaokaze/Cac2er/blob/master/src/main/kotlin/com/wcaokaze/cac2er/WeakCache.kt#L99)

sets the content. This affects all other [Cache](../-cache/index.md)s and [WeakCache](../-weak-cache/index.md)s
associated with the same file. This function doesn't write the content into
the [file](../-weak-cache/file.md). To write it at the same time, [WritableWeakCache.save](../save.md) is
useful.

**Since**
4.0.0


text:
"use strict";

/**
 * @param {Application} application - application
 */
module.exports.controller = function (application) {

    /**
     * Render "Create user" page
     *
     * @param {Object} response - expressjs response object
     * @param {(null|object)} roles - roles, @see UserUpdateOrCreateCallback
     * @param {(null|string)} error - error message, if present
     */
    function routeToUserCreate(response, roles, error = null) {
        return response.render('admin/user/user.html.twig', {
            action: 'admin.users',
            roles: roles,
            subaction: 'create',
            error: error
        });
    }

    /**
     * Create a user - page
     */
    application.getExpress().get('/admin/users/create/', (request, response) => {
        request.requestedUser = request.userManager.create();

        return routeToUserCreate(response, {});
    });

    /**
     * Create a user - handler
     */
    application.getExpress().post('/admin/users/create/', (request, response) => {
        request.requestedUser = request.userManager.create();

        validateUserActionCreateNewOrUpdateUser(request, false, function (error, roles) {
            if (error !== null) {
                return routeToUserCreate(response, roles, error);
            }

            request.userManager.add(request.requestedUser, function (error) {
                if (error === null) {
                    request.logger.info('new user [' + request.requestedUser.getName() + '] was created.');

                    request.projectManager.setUserRoleInProject(request.requestedUser.getId(), roles, function (error) {
                        if (error === null) {

                            request.logger.info(
                                'new user [' + request.requestedUser.getName() + '] roles were created.'
                            );

                            return fetchUsersByCriteria(
                                request,
                                response,
                                -1,
                                -1,
                                -1,
                                'User [' + request.requestedUser.getLogin() + '] was created.',
                                null
                            );
                        } else {
                            request.logger.error(error);

                            return routeToUserCreate(response, roles, 'Got error. Contact your system administrator.');
                        }
                    });
                } else {
                    request.logger.error(error);

                    return routeToUserCreate(response, roles, 'Got error. Contact your system administrator.');
                }
            });
        });
    });

    /**
     * Middleware to preload user if there is a userId in the url
     */
    application.getExpress().all('/admin/users/:userId/*', (request, response, next) => {
        var userId = parseInt(request.params.userId);

        if (Number.isNaN(userId)) {
            request.logger.info('user was requested by non-NAN id [' + userId + ']');

            return fetchUsersByCriteria(request, response, -1, -1, -1, null, 'Wrong user id');
        }

        request.userManager.getById(userId, (error, user) => {
            if (user === null) {
                request.logger.info('non-existed user [' + userId + '] was requested');

                return fetchUsersByCriteria(
                    request, response, -1, -1, -1, null, 'User with given id doesn\'t exist'
                );
            }

            request.requestedUser = user;
            return next();
        });
    });

    /**
     * Callback for update/create event
     *
     * @callback UserUpdateOrCreateCallback
     *
     * @param {(null|string)} error - error message, if error happened
     * @param {(null|object)} roles - will be populated new with new roles in each project for given user,
     *                                  projectId x role, null if error happened
     */

    /**
     * Validate request for create new user or update existing
     *
     * @param {Object} request - express request
     * @param {boolean} isUpdate - is it update operation or create new
     * @param {UserUpdateOrCreateCallback} callback - user update or create callback
     */
    function validateUserActionCreateNewOrUpdateUser(request, isUpdate, callback) {
        var
            name = request.body.name,
            login = request.body.login,
            password = request.body.password,
            role = request.body.role,
            hashes = {},
            roles = {};

        request.requestedUser
            .setName(name)
            .setLogin(login)
            .setRole(role);

        if (
            (typeof name === 'undefined') ||
            (typeof login === 'undefined') ||
            (typeof name === 'undefined') ||
            (typeof role === 'undefined')
        ) {
            return callback('Not enough data in the request.', null);
        }

        name = name.trim();
        login = login.trim();
        password = password.trim();
        role = parseInt(role, 10);

        if (
            (name.length < request.userManager.MIN_TEXT_FIELD_LENGTH) ||
            (login.length < request.userManager.MIN_TEXT_FIELD_LENGTH)
        ) {
            return callback(
                'Name and login should be at least ' + request.userManager.MIN_TEXT_FIELD_LENGTH + ' characters.',
                null
            );
        }

        if (!isUpdate || (password.length > 0)) {
            if (password.length < request.userManager.MIN_TEXT_FIELD_LENGTH) {
                return callback(
                    'Password should be at least ' + request.userManager.MIN_TEXT_FIELD_LENGTH + ' characters.',
                    null
                );
            }

            hashes = application.getAuth().hashPassword(password);
        } else {
            hashes = {
                hash: request.requestedUser.getPasswordHash(),
                salt: ''
            }
        }

        var userId = (isUpdate === true) ? request.requestedUser.getId() : -1;
        request.userManager.getByLogin(login, userId, function (error, foundUser) {
            if (foundUser !== null) {
                return callback('User with login [' + login + '] already exists.', null);
            }

            if (Number.isNaN(role) && !request.userManager.isRoleValid(role)) {
                return callback('New role is invalid.', null);
            }

            request.projectManager.getAllExceptLocal((error, projects) => {
                for (var projectId in projects) {
                    var roleInProject = request.body['role_' + projectId];

                    if (typeof roleInProject !== 'undefined') {
                        roleInProject = parseInt(roleInProject, 10);

                        if (roleInProject !== -1) {
                            if (!request.projectManager.isRoleValid(roleInProject)) {
                                return callback(
                                    'Role for project [' + projects[projectId].getName() + '] is invalid.',
                                    null
                                );
                            }

                            roles[projectId] = roleInProject;
                        }
                    }
                }

                request.requestedUser
                    .setName(name)
                    .setLogin(login)
                    .setRole(role)
                    .setPasswordHash(hashes.hash)
                    .setSalt(hashes.salt);

                return callback(null, roles);

            });
        });
    };

    /**
     * Render "Edit user" page
     *
     * @param {Object} response - expressjs response object
     * @param {(null|object)} roles - roles, @see UserUpdateOrCreateCallback
     * @param {(null|string)} error - error message, if present
     */
    function routeToUserEdit(response, roles, error = null) {
        return response.render('admin/user/user.html.twig', {
            action: 'admin.users',
            roles: roles,
            subaction: 'edit',
            error: error
        });
    }

    /**
     * Update user info
     */
    application.getExpress().post('/admin/users/:userId/', (request, response) => {
        if (!request.userManager.isUserSuper(request.user) && request.userManager.isUserSuper(request.requestedUser)) {
            request.logger.error('attempt to update super user data while current user is not super');

            return fetchUsersByCriteria(request, response, -1, -1, -1, null, null);
        }

        validateUserActionCreateNewOrUpdateUser(request, true, function (error, roles) {
            if (error !== null) {
                return routeToUserEdit(response, roles, error);
            }

            request.userManager.update(request.requestedUser, function (error) {
                if (error === null) {
                    request.logger.info('user [' + request.requestedUser.getName() + '] info was updated.');

                    request.projectManager.setUserRoleInProject(
                        request.requestedUser.getId(),
                        roles,
                        function (error) {
                            if (error === null) {
                                request.logger.info(
                                    'user [' + request.requestedUser.getName() + '] roles were updated.'
                                );

                                return fetchUsersByCriteria(
                                    request,
                                    response,
                                    -1,
                                    -1,
                                    -1,
                                    'User [' + request.requestedUser.getLogin() + '] info was updated.',
                                    null
                                );
                            } else {
                                request.logger.error(error);

                                return routeToUserEdit(
                                    response, roles, 'Got error. Contact your system administrator.'
                                );
                            }
                        }
                    );
                } else {
                    request.logger.error(error);

                    return routeToUserEdit(response, roles, 'Got error. Contact your system administrator.');
                }
            });
        });
    });

    /**
     * View/Edit user
     */
    application.getExpress().get('/admin/users/:userId/', (request, response) => {
        if (!request.userManager.isUserSuper(request.user) && request.userManager.isUserSuper(request.requestedUser)) {
            request.logger.error('attempt to open edit page for super user while current user is not super');

            return fetchUsersByCriteria(request, response, -1, -1, -1, null, null);
        }

        request.projectManager.getUserRoleInProjects(request.requestedUser.getId(), (error, roles) => {
            return routeToUserEdit(response, roles);
        });
    });

    /**
     * Search for users with given criteria and renders the template
     *
     * @param {Object} request - expressjs request
     * @param {Object} response - expressjs response
     * @param {number} role - search by role, -1 means any
     * @param {number} projectId - search by project, -1 means any
     * @param {number} projectRole - search by role in project, -1 means any
     * @param {(string|null)} successMessage - success message, if present
     * @param {(string|null)} errorMessage - error message, if present
     */
    function fetchUsersByCriteria(request, response, role, projectId, projectRole, successMessage, errorMessage) {
        request.userManager.searchByCriteria(role, projectId, projectRole, (error, result) => {
            return response.render('admin/user/users.html.twig', {
                action: 'admin.users',
                users: result.users,
                projects: result.projects,
                roles: result.roles,
                usersCount: Object.keys(result.users).length,
                selectedRole: role,
                selectedProject: projectId,
                selectedProjectRole: projectRole,
                success: successMessage,
                error: errorMessage
            });
        });
    }

    /**
     * View all users
     */
    application.getExpress().get('/admin/users/', (request, response) => {
        return fetchUsersByCriteria(request, response, -1, -1, -1, null, null);
    });

    /**
     * View all users with given filters
     */
    application.getExpress().post('/admin/users/', (request, response) => {
        var
            role = request.body.role,
            projectId = request.body.project,
            projectRole = request.body.project_role;

        role = parseInt((typeof role === 'undefined') ? -1 : role, 10);
        projectId = parseInt((typeof projectId === 'undefined') ? -1 : projectId, 10);
        projectRole = parseInt((typeof projectRole === 'undefined') ? -1 : projectRole, 10);

        role = Number.isNaN(role) ? -1 : role;
        projectId = Number.isNaN(projectId) ? -1 : projectId;
        projectRole = Number.isNaN(projectRole) ? -1 : projectRole;

        return fetchUsersByCriteria(request, response, role, projectId, projectRole, null, null);
    });

    /**
     * Delete user - page
     */
    application.getExpress().get('/admin/users/:userId/delete/', (request, response) => {
        if (!request.userManager.isUserSuper(request.user) && request.userManager.isUserSuper(request.requestedUser)) {
            request.logger.error('attempt to open delete page for super user while current user is not super');

            return fetchUsersByCriteria(request, response, -1, -1, -1, null, null);
        }

        response.render('admin/user/delete.html.twig', {
            action: 'admin.users'
        });
    });

    /**
     * Delete user - handler
     */
    application.getExpress().post('/admin/users/:userId/delete/', (request, response) => {
        if (!request.userManager.isUserSuper(request.user) && request.userManager.isUserSuper(request.requestedUser)) {
            request.logger.error('attempt to delete super user while current user is not super');

            return fetchUsersByCriteria(request, response, -1, -1, -1, null, null);
        }

        request.projectManager.deleteUserFromAllProjects(request.requestedUser.getId(), function (error) {
            request.logger.info('user [' + request.requestedUser.getName() + '] was deleted form all projects.');

            if (error === null) {
                request.userManager.deleteUser(request.requestedUser.getId(), function (error) {
                    if (error === null) {
                        request.logger.info('user [' + request.requestedUser.getName() + '] was deleted.');

                        return fetchUsersByCriteria(
                            request,
                            response,
                            -1,
                            -1,
                            -1,
                            'User [' + request.requestedUser.getName() + '] was deleted.',
                            null
                        );
                    } else {
                        request.logger.error(error);

                        return fetchUsersByCriteria(
                            request, response, -1, -1, -1, null, 'Got error. Contact your system administrator.'
                        );
                    }
                });
            } else {
                request.logger.error(error);

                return fetchUsersByCriteria(
                    request, response, -1, -1, -1, null, 'Got error. Contact your system administrator.'
                );
            }
        });
    });

};


text:
module Main where

import Euphs.Bot
import Euphs.Events
import Euphs.Commands
import Euphs.Types
import Euphs.Options

import Control.Concurrent.STM.TMVar
import Control.Concurrent.STM
import Control.Monad.IO.Class
import Control.Monad
import Data.List
import Data.Maybe
import Data.Function

import System.Process
import Safe

data ClientState = ClientState {
    playHandle :: TMVar ProcessHandle
}

main :: IO ()
main = do
    let myOptions = defaults {
          roomList = "music"
        , botNick = ""
        }
    opts <- getOpts myOptions options
    cbot <- clientBot
    botWithOpts cbot opts

clientBot :: IO BotFunctions
clientBot = do
    player <- atomically newEmptyTMVar
    let stat = ClientState player
    return emptyBot {
        eventsHook = myFun stat
    ,   dcHook = Just (myClean stat)
    }

myFun stat (SendEvent m) = do
    case findPlay m of
            Nothing -> return ()
            Just l -> liftIO $ playStuff stat l

myFun stat sn@SnapshotEvent{} = do
    let mes = reverse $ sortBy (compare `on` timeRecieved) $ messages sn
    case headMay (mapMaybe findPlay mes) of
        Nothing -> return ()
        Just m -> liftIO $ playStuff stat m

myFun _ _ = return ()

findPlay :: MessageData -> Maybe String
findPlay m = do
    let play = filter (isInfixOf "watch?v=")
               $ drop 1 $ dropWhile (/= "!play") $ words
               $ contentMsg m
    req <- headMay play
    return req

playStuff :: ClientState -> String -> IO ()
playStuff stat l = do
    let p = playHandle stat
    hl <- spawnProcess "youtube-viewer" ["-n","--no-interactive", l]
    tryKillVideo p
    atomically $ putTMVar p hl

tryKillVideo :: TMVar ProcessHandle -> IO ()
tryKillVideo p = do
     m <- atomically $ tryTakeTMVar p
     case m of
        Nothing -> return ()
        Just proc -> terminateProcess proc

myClean :: ClientState -> IO ()
myClean s = do
    let p = playHandle s
    tryKillVideo p


text:
Here is a small collection of tools for watching, monitoring, and
manipulating beanstalkd.

## Interactive Commands

Interactive commands are in the bin directory.

### beanstalk-stats.rb

beanstalk-stats.rb gives you a feel for how fast things are going in and out
of your queue.

    usage: beanstalk-stats.rb host:11300 host2:11300 [...]

### beanstalk-queue-stats.rb

beanstalk-queue-stats.rb watches a single beanstalk instance and shows you
which tubes contain elements, and how fast they're changing.

    usage: beanstalk-queue-stats.rb host:11300

### beanstalk-cleanup.rb

beanstalk-cleanup.rb is a continuously edited one-off script to help clean
stuff out of queues.  It pulls stuff out of the queue and defers, buries, or
deletes items based on regexes over the content.

    usage: vi beanstalk-cleanup.rb
           # edit the awesome hard-coded bury and delete rules
           beanstalk-cleanup.rb host:11300

### beanstalk-export.rb

beanstalk-export.rb will export all of the jobs from a server.  You
can use it to perform a server upgrade, or migrate all of the jobs
from one server another.

You *should* put the server in draining mode (send signal `USR1`)
before starting this to ensure new jobs aren't getting queued.  You
may also consider shutting down your workers since it may otherwise
cause jobs to be executed prematurely.

Note that the following job attributes are preserved:

* tube
* delay
* priority
* ttr
* body

Anything else (e.g. buried status or number of failures) is lost in
translation.

    usage: beanstalk-export.rb host:11300 > export.yml

### beanstalk-import.rb

beanstalk-import.rb is a tool to complement to beanstalk-export.rb by
allowing the export to be loaded into another server.

    usage: beanstalk-import.rb export.yml host:11300

## Nagios Monitoring Scripts

### beanstalk-jobs.rb

Ensures the number of jobs in the default tube fall within a reasonable range.

    usage: beanstalk-jobs.rb --host localhost --port 11300 --warn 10 --error 20

warn and error respectively set the maximum number of jobs found
before a warning or error is issued. Optionally the --tube argument can be used to restrict
statistics to a particular tube.

### beanstalk-workers.rb

Ensures that the number of workers within the queue is within range.

    usage: beanstalk-workers.rb  --host localhost --port 11300 --warn 10 --error 5

warn and error respectively specify the minimum workers
that should be in place before a warning or error is issued.
Optionally the --tube argument can be used to restrict
statistics to a particular tube.

### beanstalk-rate.rb

Ensures the growth rate of a particular stat is within range.

    usage: beanstalk-rate.rb host:11300 --host localhost --port 11300 --warnlow 0.05 --errorlow 0.01   --warnhigh 0.75 --errorhigh 0.99 --stat stat_name

All min and max values are required and are interpreted as floats.  The rates
are expressed as units per second. Optionally the --tube argument can be used to restrict
statistics to a particular tube.


text:
(function(window) {

	/**
	 * a TMX Map Reader
	 * Tiled QT 0.7.x format
	 * @class
	 * @memberOf me
	 * @constructor
	 * @ignore
	 */
	me.TMXMapReader = Object.extend({

		XMLReader : null,
		JSONReader : null,

		// temporary, the time to
		// rewrite the rest properly
		TMXParser: null,

		readMap: function (map) {
			// if already loaded, do nothing
			if (map.initialized) {
				return;
			}
			if (me.loader.getTMXFormat(map.levelId) === 'xml') {
				// create an instance of the XML Reader
				if  (this.XMLReader === null) {
					this.XMLReader = new XMLMapReader();
				}
				this.TMXParser = this.XMLReader.TMXParser;
				// load the map
				this.XMLReader.readXMLMap(map, me.loader.getTMX(map.levelId));

			}
			else /*JSON*/ {
				// create an instance of the JSON Reader
				if  (this.JSONReader === null) {
					this.JSONReader = new JSONMapReader();
				}
				this.JSONReader.readJSONMap(map, me.loader.getTMX(map.levelId));

			}

			// center the map if smaller than the current viewport
			if ((map.width < me.game.viewport.width) ||
				(map.height < me.game.viewport.height)) {
					var shiftX =  ~~( (me.game.viewport.width - map.width) / 2);
					var shiftY =  ~~( (me.game.viewport.height - map.height) / 2);
					// update the map default screen position
					map.pos.add({x:shiftX > 0 ? shiftX : 0 , y:shiftY > 0 ? shiftY : 0} );
			}

			// flag as loaded
			map.initialized = true;

		},

		/**
		 * set a compatible renderer object
		 * for the specified map
		 * TODO : put this somewhere else
		 * @ignore
		 */
		getNewDefaultRenderer: function (obj) {
			switch (obj.orientation) {
				case "orthogonal":
					return new me.TMXOrthogonalRenderer(obj.cols, obj.rows, obj.tilewidth, obj.tileheight);
				case "isometric":
					return new me.TMXIsometricRenderer(obj.cols, obj.rows , obj.tilewidth, obj.tileheight);

				// if none found, throw an exception
				default:
					throw "melonJS: " + obj.orientation + " type TMX Tile Map not supported!";
			}
		},

		/**
		 * Set tiled layer Data
		 * @ignore
		 */
		setLayerData : function(layer, data, encoding, compression) {
			// initialize the layer data array
			layer.initArray(layer.cols, layer.rows);

			// decode data based on encoding type
			switch (encoding) {
				// XML encoding
				case null:
					data = data.getElementsByTagName(me.TMX_TAG_TILE);
					break;
				// json encoding
				case 'json':
					// do nothing as data can be directly reused
					break;
				// CSV encoding
				case me.TMX_TAG_CSV:
				// Base 64 encoding
				case me.TMX_TAG_ATTR_BASE64:
					// Merge all childNodes[].nodeValue into a single one
					var nodeValue = '';
					for ( var i = 0, len = data.childNodes.length; i < len; i++) {
						nodeValue += data.childNodes[i].nodeValue;
					}
					// and then decode them
					if (encoding === me.TMX_TAG_CSV) {
						// CSV decode
						data = me.utils.decodeCSV(nodeValue, layer.cols);
					} else {
						// Base 64 decode
						data = me.utils.decodeBase64AsArray(nodeValue, 4);
						// check if data is compressed
						if (compression !== null) {
							data = me.utils.decompress(data, compression);
						}
					}
					// ensure nodeValue is deallocated
					nodeValue = null;
					break;

				default:
					throw "melonJS: TMX Tile Map " + encoding + " encoding not supported!";
			}

			var idx = 0;
			// set everything
			for ( var y = 0 ; y <layer.rows; y++) {
				for ( var x = 0; x <layer.cols; x++) {
					// get the value of the gid
					var gid = (encoding == null) ? this.TMXParser.getIntAttribute(data[idx++], me.TMX_TAG_GID) : data[idx++];
					// fill the array
					if (gid !== 0) {
						// add a new tile to the layer
						var tile = layer.setTile(x, y, gid);
						// draw the corresponding tile
						if (layer.visible && layer.preRender) {
							layer.renderer.drawTile(layer.layerSurface, x, y, tile, tile.tileset);
						}
					}
				}
			}
		}

	});

	/**
	 * a basic TMX/TSX Parser
	 * @class
	 * @constructor
	 * @ignore
	 **/
	function _TinyTMXParser() {
		var parserObj = {
			tmxDoc : null,

			// parse a TMX XML file
			setData : function(data) {
				this.tmxDoc = data;
			},

			getFirstElementByTagName : function(name) {
				return this.tmxDoc ? this.tmxDoc.getElementsByTagName(name)[0] : null;
			},

			getAllTagElements : function() {
				return this.tmxDoc ? this.tmxDoc.getElementsByTagName('*') : null;
			},

			getStringAttribute : function(elt, str, val) {
				var ret = elt.getAttribute(str);
				return ret ? ret.trim() : val;
			},

			getIntAttribute : function(elt, str, val) {
				var ret = this.getStringAttribute(elt, str, val);
				return ret ? parseInt(ret, 10) : val;
			},

			getFloatAttribute : function(elt, str, val) {
				var ret = this.getStringAttribute(elt, str, val);
				return ret ? parseFloat(ret) : val;
			},

			getBooleanAttribute : function(elt, str, val) {
				var ret = this.getStringAttribute(elt, str, val);
				return ret ? (ret === "true") : val;
			},

			// free the allocated parser
			free : function() {
				this.tmxDoc = null;
			}
		};
		return parserObj;
	}

	/**
	 * a XML Map Reader
	 * Tiled QT 0.7.x format
	 * @class
	 * @memberOf me
	 * @constructor
	 * @ignore
	 */
	var XMLMapReader = me.TMXMapReader.extend({

		TMXParser : null,

		init: function(){
			if (!this.TMXParser) {
				this.TMXParser = new _TinyTMXParser();
			}
		},

		/**
		 * initialize a map using XML data
		 * @ignore
		 */
		readXMLMap : function(map, data) {
			if (!data) {
				throw "melonJS:" + map.levelId + " TMX map not found";
			}

			// to automatically increment z index
			var zOrder = 0;

			// init the parser
			this.TMXParser.setData(data);

			// retreive all the elements of the XML file
			var xmlElements = this.TMXParser.getAllTagElements();

			// parse all tags
			for ( var i = 0; i < xmlElements.length; i++) {

				// check each Tag
				switch (xmlElements.item(i).nodeName) {
					// get the map information
					case me.TMX_TAG_MAP:
						var elements = xmlElements.item(i);
						map.version = this.TMXParser.getStringAttribute(elements, me.TMX_TAG_VERSION);
						map.orientation = this.TMXParser.getStringAttribute(elements, me.TMX_TAG_ORIENTATION);
						map.cols = this.TMXParser.getIntAttribute(elements, me.TMX_TAG_WIDTH);
						map.rows = this.TMXParser.getIntAttribute(elements, me.TMX_TAG_HEIGHT);
						map.tilewidth = this.TMXParser.getIntAttribute(elements, me.TMX_TAG_TILEWIDTH);
						map.tileheight = this.TMXParser.getIntAttribute(elements, me.TMX_TAG_TILEHEIGHT);
						map.width = map.cols * map.tilewidth;
						map.height = map.rows * map.tileheight;
						map.backgroundcolor = this.TMXParser.getStringAttribute(elements, me.TMX_BACKGROUND_COLOR);
						map.z = zOrder++;

						// set the map properties (if any)
						me.TMXUtils.applyTMXPropertiesFromXML(map, elements);

						// check if a user-defined background color is defined
						map.background_color = map.backgroundcolor ? map.backgroundcolor : map.background_color;
						if (map.background_color) {
							map.mapLayers.push(new me.ColorLayer("background_color",
																  map.background_color,
																  zOrder++));
						}

						// check if a background image is defined
						if (map.background_image) {
							// add a new image layer
							map.mapLayers.push(new me.ImageLayer("background_image",
																  map.width, map.height,
																  map.background_image,
																  zOrder++));
						}

						// initialize a default renderer
						if ((me.game.renderer === null) || !me.game.renderer.canRender(map)) {
							me.game.renderer = this.getNewDefaultRenderer(map);
						}

						break;

					// get the tileset information
					case me.TMX_TAG_TILESET:
					   // Initialize our object if not yet done
					   if (!map.tilesets) {
						  map.tilesets = new me.TMXTilesetGroup();
					   }
					   // add the new tileset
					   map.tilesets.add(this.readTileset(xmlElements.item(i)));
					   break;

					// get image layer information
					case me.TMX_TAG_IMAGE_LAYER:
						map.mapLayers.push(this.readImageLayer(map, xmlElements.item(i), zOrder++));
						break;

					// get the layer(s) information
					case me.TMX_TAG_LAYER:
						// regular layer or collision layer
						map.mapLayers.push(this.readLayer(map, xmlElements.item(i), zOrder++));
						break;

					// get the object groups information
					case me.TMX_TAG_OBJECTGROUP:
					   map.objectGroups.push(this.readObjectGroup(map, xmlElements.item(i), zOrder++));
					   break;

					default:
						// ignore unrecognized tags
						break;

				} // end switch

			} // end for

			// free the TMXParser ressource
			this.TMXParser.free();
		},

		readLayer: function (map, data, z) {
			var layer = new me.TMXLayer(map.tilewidth, map.tileheight, map.orientation, map.tilesets, z);
			// init the layer properly
			layer.initFromXML(data);

			// check data encoding/compression type
			var layerData = data.getElementsByTagName(me.TMX_TAG_DATA)[0];
			var encoding = this.TMXParser.getStringAttribute(layerData, me.TMX_TAG_ENCODING, null);
			var compression = this.TMXParser.getStringAttribute(layerData, me.TMX_TAG_COMPRESSION, null);
			// make sure this is not happening
			if (encoding === '') {
				encoding = null;
			}
			if (compression === '') {
				compression = null;
			}

			// associate a renderer to the layer (if not a collision layer)
			if (!layer.isCollisionMap || me.debug.renderCollisionMap) {
				if (!me.game.renderer.canRender(layer)) {
					layer.setRenderer(me.mapReader.getNewDefaultRenderer(layer));
				} else {
					// use the default one
					layer.setRenderer(me.game.renderer);
				}
			}

			// parse the layer data
			this.setLayerData(layer, layerData, encoding, compression);
			// free layerData
			layerData = null;

			return layer;
		},

		readImageLayer: function(map, data, z) {
			// extract layer information
			var iln = this.TMXParser.getStringAttribute(data, me.TMX_TAG_NAME);
			var ilw = this.TMXParser.getIntAttribute(data, me.TMX_TAG_WIDTH);
			var ilh = this.TMXParser.getIntAttribute(data, me.TMX_TAG_HEIGHT);
			var ilsrc = data.getElementsByTagName(me.TMX_TAG_IMAGE)[0].getAttribute(me.TMX_TAG_SOURCE);

			// create the layer
			var imageLayer = new me.ImageLayer(iln, ilw * map.tilewidth, ilh * map.tileheight, ilsrc, z);

			// set some additional flags
			imageLayer.visible = (this.TMXParser.getIntAttribute(data, me.TMX_TAG_VISIBLE, 1) === 1);
			imageLayer.setOpacity(this.TMXParser.getFloatAttribute(data, me.TMX_TAG_OPACITY, 1.0));

			// check if we have any properties
			me.TMXUtils.applyTMXPropertiesFromXML(imageLayer, data);

			// make sure ratio is a vector (backward compatibility)
			if (typeof(imageLayer.ratio) === "number") {
				imageLayer.ratio = new me.Vector2d(parseFloat(imageLayer.ratio), parseFloat(imageLayer.ratio));
			}

			// add the new layer
			return imageLayer;

		},

		readTileset : function (data) {
			var tileset = new me.TMXTileset();
			tileset.initFromXML(data);
			return tileset;
		},

		readObjectGroup: function(map, data, z) {
			var name = this.TMXParser.getStringAttribute(data, me.TMX_TAG_NAME);
			var group = new me.TMXObjectGroup();
			group.initFromXML(name, data, map.tilesets, z);
			return group;
		}

	});

	/**
	 * a JSON Map Reader
	 * Tiled QT 0.7.x format
	 * @class
	 * @memberOf me
	 * @constructor
	 * @ignore
	 */
	var JSONMapReader = me.TMXMapReader.extend({

		readJSONMap: function (map, data) {
			if (!data) {
				throw "melonJS:" + map.levelId + " TMX map not found";
			}

			// to automatically increment z index
			var zOrder = 0;

			// keep a reference to our scope
			var self = this;

			// map information
			map.version = data[me.TMX_TAG_VERSION];
			map.orientation = data[me.TMX_TAG_ORIENTATION];
			map.cols = parseInt(data[me.TMX_TAG_WIDTH], 10);
			map.rows = parseInt(data[me.TMX_TAG_HEIGHT], 10);
			map.tilewidth = parseInt(data[me.TMX_TAG_TILEWIDTH], 10);
			map.tileheight = parseInt(data[me.TMX_TAG_TILEHEIGHT], 10);
			map.width = map.cols * map.tilewidth;
			map.height = map.rows * map.tileheight;
			map.backgroundcolor = data[me.TMX_BACKGROUND_COLOR];
			map.z = zOrder++;

			// set the map properties (if any)
			me.TMXUtils.applyTMXPropertiesFromJSON(map, data);

			// check if a user-defined background color is defined
			map.background_color = map.backgroundcolor ? map.backgroundcolor : map.background_color;
			if (map.background_color) {
				map.mapLayers.push(new me.ColorLayer("background_color",
													  map.background_color,
													  zOrder++));
			}

			// check if a background image is defined
			if (map.background_image) {
				// add a new image layer
				map.mapLayers.push(new me.ImageLayer("background_image",
													  map.width, map.height,
													  map.background_image,
													  zOrder++));
			}

			// initialize a default renderer
			if ((me.game.renderer === null) || !me.game.renderer.canRender(map)) {
				me.game.renderer = this.getNewDefaultRenderer(map);
			}

			// Tileset information
			if (!map.tilesets) {
				// make sure we have a TilesetGroup Object
				map.tilesets = new me.TMXTilesetGroup();
			}
			// parse all tileset objects
			data["tilesets"].forEach(function(tileset) {
				// add the new tileset
				map.tilesets.add(self.readTileset(tileset));
			});

			// get layers information
			data["layers"].forEach(function(layer) {
				switch (layer.type) {
					case me.TMX_TAG_IMAGE_LAYER :
						map.mapLayers.push(self.readImageLayer(map, layer, zOrder++));
						break;

					case me.TMX_TAG_TILE_LAYER :
						map.mapLayers.push(self.readLayer(map, layer, zOrder++));
						break;

					// get the object groups information
					case me.TMX_TAG_OBJECTGROUP:
						map.objectGroups.push(self.readObjectGroup(map, layer, zOrder++));
						break;

					default: break;
				}
			});

			// FINISH !
		},

		readLayer: function (map, data, z) {
			var layer = new me.TMXLayer(map.tilewidth, map.tileheight, map.orientation, map.tilesets, z);
			// init the layer properly
			layer.initFromJSON(data);
			// associate a renderer to the layer (if not a collision layer)
			if (!layer.isCollisionMap) {
				if (!me.game.renderer.canRender(layer)) {
					layer.setRenderer(me.mapReader.getNewDefaultRenderer(layer));
				} else {
					// use the default one
					layer.setRenderer(me.game.renderer);
				}
			}
			// parse the layer data
			this.setLayerData(layer, data[me.TMX_TAG_DATA], 'json', null);
			return layer;
		},

		readImageLayer: function(map, data, z) {
			// extract layer information
			var iln = data[me.TMX_TAG_NAME];
			var ilw = parseInt(data[me.TMX_TAG_WIDTH], 10);
			var ilh = parseInt(data[me.TMX_TAG_HEIGHT], 10);
			var ilsrc = data[me.TMX_TAG_IMAGE];

			// create the layer
			var imageLayer = new me.ImageLayer(iln, ilw * map.tilewidth, ilh * map.tileheight, ilsrc, z);

			// set some additional flags
			imageLayer.visible = data[me.TMX_TAG_VISIBLE];
			imageLayer.setOpacity(parseFloat(data[me.TMX_TAG_OPACITY]));

			// check if we have any additional properties
			me.TMXUtils.applyTMXPropertiesFromJSON(imageLayer, data);

			// make sure ratio is a vector (backward compatibility)
			if (typeof(imageLayer.ratio) === "number") {
				imageLayer.ratio = new me.Vector2d(parseFloat(imageLayer.ratio), parseFloat(imageLayer.ratio));
			}

			return imageLayer;
		},

		readTileset : function (data) {
			var tileset = new me.TMXTileset();
			tileset.initFromJSON(data);
			return tileset;
		},

		readObjectGroup: function(map, data, z) {
			var group = new me.TMXObjectGroup();
			group.initFromJSON(data[me.TMX_TAG_NAME], data, map.tilesets, z);
			return group;
		}

	});

})(window);


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace JSonParser.SDK
{
    public class CSharpFile
    {
        public string Name { get; set; }
        public string Content { get; set; }
    }
}


text:
                Thaler
                <input type="number" class="sheet-number-box-small" value="0" name="attr_player-thaler" style="width:4em;"/>

                Shilling
                <input type="number" class="sheet-number-box-small" value="0" name="attr_player-shilling" style="width:4em;"/>

                Orteg
                <input type="number" class="sheet-number-box-small" value="0" name="attr_player-orteg" style="width:4em;"/>

                    Detailed Equipment & Artifacts

                            <input type="checkbox" name="attr_artifact-isBound" title="Bound to player" data-i18n-title="title-bond-to-player" />
                            <input type="text" name="attr_artifact-name" title="Name" data-i18n-title="name" placeholder="Name" data-i18n-placeholder="name" style="width: 55%;" />
                            <select name="attr_artifact-corruption" title="Temporary Corruption when equipment or artifacts is used" data-i18n-title="title-temporary-corruption-when-equipment-is-used" style="width: 15%">
                                    <option value="0" selected>-</option>
                                    <option value="[[1]]" >1</option>
                                    <option value="[[1d4]]" >1d4</option>
                                    <option value="[[1d6]]" >1d6</option>
                                    <option value="[[1d8]]" >1d8</option>
                            </select>
                            Temp Corruption

                        <textarea name="attr_artifact-description" style="height:2em" title="Description" data-i18n-title="description" placeholder="Description" data-i18n-placeholder="description"></textarea>

                    <fieldset class="repeating_artifacts" style="margin-bottom:4px">

                            <input type="checkbox" name="attr_artifact-isBound" title="Bound to player" data-i18n-title="title-bond-to-player" />
                            <input type="text" name="attr_artifact-name" title="Name" data-i18n-title="name" placeholder="Name" data-i18n-placeholder="name" />
                            <select name="attr_artifact-corruption" title="Temporary Corruption when equipment or artifacts is used" data-i18n-title="title-temporary-corruption-when-equipment-is-used">
                                    <option value="0" selected>-</option>
                                    <option value="[[1]]" >1</option>
                                    <option value="[[1d4]]" >1d4</option>
                                    <option value="[[1d6]]" >1d6</option>
                                    <option value="[[1d8]]" >1d8</option>
                            </select>
                            Temp Corruption

                        <textarea name="attr_artifact-description" style="height:2em" title="Description" data-i18n-title="description" placeholder="Description" data-i18n-placeholder="description"></textarea>
                    </fieldset>

                    Items

                        <input type="text" style="width:290px" name="attr_item-sleeping-roll" title="Standard Equipment" data-i18n-title="title-standard-equipment" value="Sleeping roll"/>
                        <input type="number" class="sheet-number-box-small" name="attr_item-sleeping-roll-quantity" value="1" title="Item Quantity" data-i18n-title="title-item-quantity" style="width:5em;text-align:left;padding-left:.5em;"/>

                        <input type="text" style="width:290px" name="attr_item-cooking-pan" title="Standard Equipment" data-i18n-title="title-standard-equipment" value="Cooking equipment"/>
                        <input type="number" class="sheet-number-box-small" name="attr_item-cooking-pan-quantity" value="1" title="Item Quantity" data-i18n-title="title-item-quantity" style="width:5em;text-align:left;padding-left:.5em;"/>

                        <input type="text" style="width:290px" name="attr_item-firewood" title="Standard Equipment" data-i18n-title="title-standard-equipment" value="Firewood"/>
                        <input type="number" class="sheet-number-box-small" name="attr_item-firewood-quantity" value="1" title="Item Quantity" data-i18n-title="title-item-quantity" style="width:5em;text-align:left;padding-left:.5em;"/>

                        <input type="text" style="width:290px" name="attr_item-flint-and-steel" title="Standard Equipment" data-i18n-title="title-standard-equipment" value="Flint and Steel"/>
                        <input type="number" class="sheet-number-box-small" name="attr_item-flint-and-steel-quantity" value="1" title="Item Quantity" data-i18n-title="title-item-quantity" style="width:5em;text-align:left;padding-left:.5em;"/>

                        <input type="text" style="width:290px" name="attr_item-rope" title="Standard Equipment" data-i18n-title="title-standard-equipment" value="Rope"/>
                        <input type="number" class="sheet-number-box-small" name="attr_item-rope-quantity" value="1" title="Item Quantity" data-i18n-title="title-item-quantity" style="width:5em;text-align:left;padding-left:.5em;"/>

                        <input type="text" style="width:290px" name="attr_item-waterskin" title="Standard Equipment" data-i18n-title="title-standard-equipment" value="Waterskin"/>
                        <input type="number" class="sheet-number-box-small" name="attr_item-waterskin-quantity" value="1" title="Item Quantity" data-i18n-title="title-item-quantity" style="width:5em;text-align:left;padding-left:.5em;"/>

                    <fieldset class="repeating_item">
                        <input type="text" style="width:290px" name="attr_item-name" title="Item Name" data-i18n-title="title-item-name" placeholder="Item Name" data-i18n-placeholder="item-name" />
                        <input type="number" class="sheet-number-box-small" name="attr_item-quantity" value="1" title="Item Quantity" data-i18n-title="title-item-quantity" style="width:5em;text-align:left;padding-left:.5em;"/>
                    </fieldset>

                    Character Background
                    <textarea name="attr_background" data-i18n-title="character-background" title="Explain where your character comes from and where he or she wants to go and accomplish." placeholder="Explain where your character comes from and where he or she wants to go and accomplish." data-i18n-placeholder="character-background"></textarea>
                    <textarea name="attr_character_goal" style="height:3.5em;" title="Character Goal" data-i18n-title="character-goal" placeholder="Character Goal" data-i18n-placeholder="character-goal"></textarea>

                    Group
                    <input type="text" name="attr_groupName" title="Group Name" data-i18n-title="group-name" placeholder="Group Name" data-i18n-placeholder="group-name" />
                    <textarea name="attr_groupGoal" style="height:3.5em;" title="Group Goal" data-i18n-title="group-goal" placeholder="Group Goal" data-i18n-placeholder="group-goal"></textarea>

                    Friends

                        <input type="text" name="attr_friendName" title="Friend Name" data-i18n-title="friends-name" placeholder="Friend Name" data-i18n-placeholder="friends-name" />
                        <input type="text" name="attr_friendRace" title="Friend Race" data-i18n-title="friends-race" placeholder="Friend Race" data-i18n-placeholder="friends-race" />
                        <input type="text" name="attr_friendOccupation" title="Friend Occupation" data-i18n-title="friends-occupation" placeholder="Friend Occupation" data-i18n-placeholder="friends-occupation" />
                        <input type="text" name="attr_friendPlayer" title="Player" data-i18n-title="player" placeholder="Player" data-i18n-placeholder="player" />

                    <fieldset class="repeating_friends-list">

                            <input type="text" name="attr_friendName" title="Friend Name" data-i18n-title="friends-name" placeholder="Friend Name" data-i18n-placeholder="friends-name" />
                            <input type="text" name="attr_friendRace" title="Friend Race" data-i18n-title="friends-race" placeholder="Friend Race" data-i18n-placeholder="friends-race" />
                            <input type="text" name="attr_friendOccupation" title="Friend Occupation" data-i18n-title="friends-occupation" placeholder="Friend Occupation" data-i18n-placeholder="friends-occupation" />
                            <input type="text" name="attr_friendPlayer" title="Player" data-i18n-title="player" placeholder="Player" data-i18n-placeholder="player" />

                    </fieldset>