text:
package org.elasticsearch.index.mapper.core;

import com.carrotsearch.hppc.ObjectOpenHashSet;
import com.carrotsearch.hppc.cursors.ObjectCursor;
import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.TermFilter;
import org.apache.lucene.queries.TermsFilter;
import org.apache.lucene.search.*;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.lucene.search.RegexpFilter;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.codec.docvaluesformat.DocValuesFormatProvider;
import org.elasticsearch.index.codec.docvaluesformat.DocValuesFormatService;
import org.elasticsearch.index.codec.postingsformat.PostingFormats;
import org.elasticsearch.index.codec.postingsformat.PostingsFormatProvider;
import org.elasticsearch.index.codec.postingsformat.PostingsFormatService;
import org.elasticsearch.index.fielddata.FieldDataType;
import org.elasticsearch.index.mapper.*;
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
import org.elasticsearch.index.mapper.object.ObjectMapper;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.search.FieldDataTermsFilter;
import org.elasticsearch.index.similarity.SimilarityLookupService;
import org.elasticsearch.index.similarity.SimilarityProvider;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 *
 */
public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {

    public static class Defaults {
        public static final FieldType FIELD_TYPE = new FieldType();
        public static final boolean DOC_VALUES = false;

        static {
            FIELD_TYPE.setIndexed(true);
            FIELD_TYPE.setTokenized(true);
            FIELD_TYPE.setStored(false);
            FIELD_TYPE.setStoreTermVectors(false);
            FIELD_TYPE.setOmitNorms(false);
            FIELD_TYPE.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
            FIELD_TYPE.freeze();
        }

        public static final float BOOST = 1.0f;
        public static final ContentPath.Type PATH_TYPE = ContentPath.Type.FULL;
    }

    public abstract static class Builder<T extends Builder, Y extends AbstractFieldMapper> extends Mapper.Builder<T, Y> {

        protected final FieldType fieldType;
        protected Boolean docValues;
        protected float boost = Defaults.BOOST;
        protected boolean omitNormsSet = false;
        protected String indexName;
        protected NamedAnalyzer indexAnalyzer;
        protected NamedAnalyzer searchAnalyzer;
        protected Boolean includeInAll;
        protected boolean indexOptionsSet = false;
        protected PostingsFormatProvider postingsProvider;
        protected DocValuesFormatProvider docValuesProvider;
        protected SimilarityProvider similarity;
        protected Loading normsLoading;
        @Nullable
        protected Settings fieldDataSettings;
        protected final MultiFields.Builder multiFieldsBuilder;
        protected CopyTo copyTo;

        protected Builder(String name, FieldType fieldType) {
            super(name);
            this.fieldType = fieldType;
            multiFieldsBuilder = new MultiFields.Builder();
        }

        public T index(boolean index) {
            this.fieldType.setIndexed(index);
            return builder;
        }

        public T store(boolean store) {
            this.fieldType.setStored(store);
            return builder;
        }

        public T docValues(boolean docValues) {
            this.docValues = docValues;
            return builder;
        }

        public T storeTermVectors(boolean termVectors) {
            if (termVectors) {
                this.fieldType.setStoreTermVectors(termVectors);
            } // don't set it to false, it is default and might be flipped by a more specific option
            return builder;
        }

        public T storeTermVectorOffsets(boolean termVectorOffsets) {
            if (termVectorOffsets) {
                this.fieldType.setStoreTermVectors(termVectorOffsets);
            }
            this.fieldType.setStoreTermVectorOffsets(termVectorOffsets);
            return builder;
        }

        public T storeTermVectorPositions(boolean termVectorPositions) {
            if (termVectorPositions) {
                this.fieldType.setStoreTermVectors(termVectorPositions);
            }
            this.fieldType.setStoreTermVectorPositions(termVectorPositions);
            return builder;
        }

        public T storeTermVectorPayloads(boolean termVectorPayloads) {
            if (termVectorPayloads) {
                this.fieldType.setStoreTermVectors(termVectorPayloads);
            }
            this.fieldType.setStoreTermVectorPayloads(termVectorPayloads);
            return builder;
        }

        public T tokenized(boolean tokenized) {
            this.fieldType.setTokenized(tokenized);
            return builder;
        }

        public T boost(float boost) {
            this.boost = boost;
            return builder;
        }

        public T omitNorms(boolean omitNorms) {
            this.fieldType.setOmitNorms(omitNorms);
            this.omitNormsSet = true;
            return builder;
        }

        public T indexOptions(IndexOptions indexOptions) {
            this.fieldType.setIndexOptions(indexOptions);
            this.indexOptionsSet = true;
            return builder;
        }

        public T indexName(String indexName) {
            this.indexName = indexName;
            return builder;
        }

        public T indexAnalyzer(NamedAnalyzer indexAnalyzer) {
            this.indexAnalyzer = indexAnalyzer;
            return builder;
        }

        public T searchAnalyzer(NamedAnalyzer searchAnalyzer) {
            this.searchAnalyzer = searchAnalyzer;
            return builder;
        }

        public T includeInAll(Boolean includeInAll) {
            this.includeInAll = includeInAll;
            return builder;
        }

        public T postingsFormat(PostingsFormatProvider postingsFormat) {
            this.postingsProvider = postingsFormat;
            return builder;
        }

        public T docValuesFormat(DocValuesFormatProvider docValuesFormat) {
            this.docValuesProvider = docValuesFormat;
            return builder;
        }

        public T similarity(SimilarityProvider similarity) {
            this.similarity = similarity;
            return builder;
        }

        public T normsLoading(Loading normsLoading) {
            this.normsLoading = normsLoading;
            return builder;
        }

        public T fieldDataSettings(Settings settings) {
            this.fieldDataSettings = settings;
            return builder;
        }

        public T multiFieldPathType(ContentPath.Type pathType) {
            multiFieldsBuilder.pathType(pathType);
            return builder;
        }

        public T addMultiField(Mapper.Builder mapperBuilder) {
            multiFieldsBuilder.add(mapperBuilder);
            return builder;
        }

        public T copyTo(CopyTo copyTo) {
            this.copyTo = copyTo;
            return builder;
        }

        public Names buildNames(BuilderContext context) {
            return new Names(name, buildIndexName(context), indexName == null ? name : indexName, buildFullName(context), context.path().sourcePath());
        }

        public String buildIndexName(BuilderContext context) {
            String actualIndexName = indexName == null ? name : indexName;
            return context.path().pathAsText(actualIndexName);
        }

        public String buildFullName(BuilderContext context) {
            return context.path().fullPathAsText(name);
        }
    }

    private static final ThreadLocal<List<Field>> FIELD_LIST = new ThreadLocal<List<Field>>() {
        protected List<Field> initialValue() {
            return new ArrayList<>(2);
        }
    };

    protected final Names names;
    protected float boost;
    protected FieldType fieldType;
    private final boolean docValues;
    protected final NamedAnalyzer indexAnalyzer;
    protected NamedAnalyzer searchAnalyzer;
    protected PostingsFormatProvider postingsFormat;
    protected DocValuesFormatProvider docValuesFormat;
    protected final SimilarityProvider similarity;
    protected Loading normsLoading;
    protected Settings customFieldDataSettings;
    protected FieldDataType fieldDataType;
    protected final MultiFields multiFields;
    protected CopyTo copyTo;

    protected AbstractFieldMapper(Names names, float boost, FieldType fieldType, Boolean docValues, NamedAnalyzer indexAnalyzer,
                                  NamedAnalyzer searchAnalyzer, PostingsFormatProvider postingsFormat,
                                  DocValuesFormatProvider docValuesFormat, SimilarityProvider similarity,
                                  Loading normsLoading, @Nullable Settings fieldDataSettings, Settings indexSettings) {
        this(names, boost, fieldType, docValues, indexAnalyzer, searchAnalyzer, postingsFormat, docValuesFormat, similarity,
                normsLoading, fieldDataSettings, indexSettings, MultiFields.empty(), null);
    }

    protected AbstractFieldMapper(Names names, float boost, FieldType fieldType, Boolean docValues, NamedAnalyzer indexAnalyzer,
                                  NamedAnalyzer searchAnalyzer, PostingsFormatProvider postingsFormat,
                                  DocValuesFormatProvider docValuesFormat, SimilarityProvider similarity,
                                  Loading normsLoading, @Nullable Settings fieldDataSettings, Settings indexSettings, MultiFields multiFields, CopyTo copyTo) {
        this.names = names;
        this.boost = boost;
        this.fieldType = fieldType;
        this.fieldType.freeze();

        // automatically set to keyword analyzer if its indexed and not analyzed
        if (indexAnalyzer == null && !this.fieldType.tokenized() && this.fieldType.indexed()) {
            this.indexAnalyzer = Lucene.KEYWORD_ANALYZER;
        } else {
            this.indexAnalyzer = indexAnalyzer;
        }
        // automatically set to keyword analyzer if its indexed and not analyzed
        if (searchAnalyzer == null && !this.fieldType.tokenized() && this.fieldType.indexed()) {
            this.searchAnalyzer = Lucene.KEYWORD_ANALYZER;
        } else {
            this.searchAnalyzer = searchAnalyzer;
        }
        if (postingsFormat == null) {
            if (defaultPostingFormat() != null) {
                postingsFormat = PostingFormats.getAsProvider(defaultPostingFormat());
            }
        }
        this.postingsFormat = postingsFormat;
        this.docValuesFormat = docValuesFormat;
        this.similarity = similarity;
        this.normsLoading = normsLoading;

        this.customFieldDataSettings = fieldDataSettings;
        if (fieldDataSettings == null) {
            this.fieldDataType = defaultFieldDataType();
        } else {
            // create a new field data type, with the default settings as well as the "new ones"
            this.fieldDataType = new FieldDataType(defaultFieldDataType().getType(),
                    ImmutableSettings.builder().put(defaultFieldDataType().getSettings()).put(fieldDataSettings)
            );
        }
        if (docValues != null) {
            this.docValues = docValues;
        } else if (fieldDataType == null) {
            this.docValues = false;
        } else {
            this.docValues = FieldDataType.DOC_VALUES_FORMAT_VALUE.equals(fieldDataType.getFormat(indexSettings));
        }
        this.multiFields = multiFields;
        this.copyTo = copyTo;
    }

    @Nullable
    protected String defaultPostingFormat() {
        return null;
    }

    @Nullable
    protected String defaultDocValuesFormat() {
        return null;
    }

    @Override
    public String name() {
        return names.name();
    }

    @Override
    public Names names() {
        return this.names;
    }

    public abstract FieldType defaultFieldType();

    public abstract FieldDataType defaultFieldDataType();

    @Override
    public final FieldDataType fieldDataType() {
        return fieldDataType;
    }

    @Override
    public FieldType fieldType() {
        return fieldType;
    }

    @Override
    public float boost() {
        return this.boost;
    }

    @Override
    public Analyzer indexAnalyzer() {
        return this.indexAnalyzer;
    }

    @Override
    public Analyzer searchAnalyzer() {
        return this.searchAnalyzer;
    }

    @Override
    public Analyzer searchQuoteAnalyzer() {
        return this.searchAnalyzer;
    }

    @Override
    public SimilarityProvider similarity() {
        return similarity;
    }

    @Override
    public CopyTo copyTo() {
        return copyTo;
    }

    @Override
    public void parse(ParseContext context) throws IOException {
        final List<Field> fields = FIELD_LIST.get();
        assert fields.isEmpty();
        try {
            parseCreateField(context, fields);
            for (Field field : fields) {
                if (!customBoost()) {
                    field.setBoost(boost);
                }
                if (context.listener().beforeFieldAdded(this, field, context)) {
                    context.doc().add(field);
                }
            }
        } catch (Exception e) {
            throw new MapperParsingException("failed to parse [" + names.fullName() + "]", e);
        } finally {
            fields.clear();
        }
        multiFields.parse(this, context);
        if (copyTo != null) {
            copyTo.parse(context);
        }
    }

    /**
     * Parse the field value and populate fields.
     */
    protected abstract void parseCreateField(ParseContext context, List<Field> fields) throws IOException;

    /**
     * Derived classes can override it to specify that boost value is set by derived classes.
     */
    protected boolean customBoost() {
        return false;
    }

    @Override
    public void traverse(FieldMapperListener fieldMapperListener) {
        fieldMapperListener.fieldMapper(this);
        multiFields.traverse(fieldMapperListener);
    }

    @Override
    public void traverse(ObjectMapperListener objectMapperListener) {
        // nothing to do here...
    }

    @Override
    public Object valueForSearch(Object value) {
        return value;
    }

    @Override
    public BytesRef indexedValueForSearch(Object value) {
        return BytesRefs.toBytesRef(value);
    }

    @Override
    public Query queryStringTermQuery(Term term) {
        return null;
    }

    @Override
    public boolean useTermQueryWithQueryString() {
        return false;
    }

    @Override
    public Query termQuery(Object value, @Nullable QueryParseContext context) {
        return new TermQuery(names().createIndexNameTerm(indexedValueForSearch(value)));
    }

    @Override
    public Filter termFilter(Object value, @Nullable QueryParseContext context) {
        return new TermFilter(names().createIndexNameTerm(indexedValueForSearch(value)));
    }

    @Override
    public Filter termsFilter(List values, @Nullable QueryParseContext context) {
        BytesRef[] bytesRefs = new BytesRef[values.size()];
        for (int i = 0; i < bytesRefs.length; i++) {
            bytesRefs[i] = indexedValueForSearch(values.get(i));
        }
        return new TermsFilter(names.indexName(), bytesRefs);
    }

    /**
     * A terms filter based on the field data cache
     */
    @Override
    public Filter fieldDataTermsFilter(List values, @Nullable QueryParseContext context) {
        // create with initial size large enough to avoid rehashing
        ObjectOpenHashSet<BytesRef> terms =
                new ObjectOpenHashSet<>((int) (values.size() * (1 + ObjectOpenHashSet.DEFAULT_LOAD_FACTOR)));
        for (int i = 0, len = values.size(); i < len; i++) {
            terms.add(indexedValueForSearch(values.get(i)));
        }

        return FieldDataTermsFilter.newBytes(context.getForField(this), terms);
    }

    @Override
    public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
        return new TermRangeQuery(names.indexName(),
                lowerTerm == null ? null : indexedValueForSearch(lowerTerm),
                upperTerm == null ? null : indexedValueForSearch(upperTerm),
                includeLower, includeUpper);
    }

    @Override
    public Filter rangeFilter(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, @Nullable QueryParseContext context) {
        return new TermRangeFilter(names.indexName(),
                lowerTerm == null ? null : indexedValueForSearch(lowerTerm),
                upperTerm == null ? null : indexedValueForSearch(upperTerm),
                includeLower, includeUpper);
    }

    @Override
    public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
        return new FuzzyQuery(names.createIndexNameTerm(indexedValueForSearch(value)), fuzziness.asDistance(value), prefixLength, maxExpansions, transpositions);
    }

    @Override
    public Query prefixQuery(Object value, @Nullable MultiTermQuery.RewriteMethod method, @Nullable QueryParseContext context) {
        PrefixQuery query = new PrefixQuery(names().createIndexNameTerm(indexedValueForSearch(value)));
        if (method != null) {
            query.setRewriteMethod(method);
        }
        return query;
    }

    @Override
    public Filter prefixFilter(Object value, @Nullable QueryParseContext context) {
        return new PrefixFilter(names().createIndexNameTerm(indexedValueForSearch(value)));
    }

    @Override
    public Query regexpQuery(Object value, int flags, @Nullable MultiTermQuery.RewriteMethod method, @Nullable QueryParseContext context) {
        RegexpQuery query = new RegexpQuery(names().createIndexNameTerm(indexedValueForSearch(value)), flags);
        if (method != null) {
            query.setRewriteMethod(method);
        }
        return query;
    }

    @Override
    public Filter regexpFilter(Object value, int flags, @Nullable QueryParseContext parseContext) {
        return new RegexpFilter(names().createIndexNameTerm(indexedValueForSearch(value)), flags);
    }

    @Override
    public Filter nullValueFilter() {
        return null;
    }

    @Override
    public void merge(Mapper mergeWith, MergeContext mergeContext) throws MergeMappingException {
        if (!this.getClass().equals(mergeWith.getClass())) {
            String mergedType = mergeWith.getClass().getSimpleName();
            if (mergeWith instanceof AbstractFieldMapper) {
                mergedType = ((AbstractFieldMapper) mergeWith).contentType();
            }
            mergeContext.addConflict("mapper [" + names.fullName() + "] of different type, current_type [" + contentType() + "], merged_type [" + mergedType + "]");
            // different types, return
            return;
        }
        AbstractFieldMapper fieldMergeWith = (AbstractFieldMapper) mergeWith;
        if (this.fieldType().indexed() != fieldMergeWith.fieldType().indexed() || this.fieldType().tokenized() != fieldMergeWith.fieldType().tokenized()) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different index values");
        }
        if (this.fieldType().stored() != fieldMergeWith.fieldType().stored()) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different store values");
        }
        if (!this.hasDocValues() && fieldMergeWith.hasDocValues()) {
            // don't add conflict if this mapper has doc values while the mapper to merge doesn't since doc values are implicitely set
            // when the doc_values field data format is configured
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different " + TypeParsers.DOC_VALUES + " values");
        }
        if (this.fieldType().omitNorms() && !fieldMergeWith.fieldType.omitNorms()) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] cannot enable norms (`norms.enabled`)");
        }
        if (this.fieldType().tokenized() != fieldMergeWith.fieldType().tokenized()) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different tokenize values");
        }
        if (this.fieldType().storeTermVectors() != fieldMergeWith.fieldType().storeTermVectors()) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different store_term_vector values");
        }
        if (this.fieldType().storeTermVectorOffsets() != fieldMergeWith.fieldType().storeTermVectorOffsets()) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different store_term_vector_offsets values");
        }
        if (this.fieldType().storeTermVectorPositions() != fieldMergeWith.fieldType().storeTermVectorPositions()) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different store_term_vector_positions values");
        }
        if (this.fieldType().storeTermVectorPayloads() != fieldMergeWith.fieldType().storeTermVectorPayloads()) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different store_term_vector_payloads values");
        }
        if (this.indexAnalyzer == null) {
            if (fieldMergeWith.indexAnalyzer != null) {
                mergeContext.addConflict("mapper [" + names.fullName() + "] has different index_analyzer");
            }
        } else if (fieldMergeWith.indexAnalyzer == null) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different index_analyzer");
        } else if (!this.indexAnalyzer.name().equals(fieldMergeWith.indexAnalyzer.name())) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different index_analyzer");
        }
        if (!this.names().equals(fieldMergeWith.names())) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different index_name");
        }

        if (this.similarity == null) {
            if (fieldMergeWith.similarity() != null) {
                mergeContext.addConflict("mapper [" + names.fullName() + "] has different similarity");
            }
        } else if (fieldMergeWith.similarity() == null) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different similarity");
        } else if (!this.similarity().equals(fieldMergeWith.similarity())) {
            mergeContext.addConflict("mapper [" + names.fullName() + "] has different similarity");
        }
        multiFields.merge(mergeWith, mergeContext);

        if (!mergeContext.mergeFlags().simulate()) {
            // apply changeable values
            this.fieldType = new FieldType(this.fieldType);
            this.fieldType.setOmitNorms(fieldMergeWith.fieldType.omitNorms());
            this.fieldType.freeze();
            this.boost = fieldMergeWith.boost;
            this.normsLoading = fieldMergeWith.normsLoading;
            this.copyTo = fieldMergeWith.copyTo;
            if (fieldMergeWith.postingsFormat != null) {
                this.postingsFormat = fieldMergeWith.postingsFormat;
            }
            if (fieldMergeWith.docValuesFormat != null) {
                this.docValuesFormat = fieldMergeWith.docValuesFormat;
            }
            if (fieldMergeWith.searchAnalyzer != null) {
                this.searchAnalyzer = fieldMergeWith.searchAnalyzer;
            }
            if (fieldMergeWith.customFieldDataSettings != null) {
                if (!Objects.equal(fieldMergeWith.customFieldDataSettings, this.customFieldDataSettings)) {
                    this.customFieldDataSettings = fieldMergeWith.customFieldDataSettings;
                    this.fieldDataType = new FieldDataType(defaultFieldDataType().getType(),
                            ImmutableSettings.builder().put(defaultFieldDataType().getSettings()).put(this.customFieldDataSettings)
                    );
                }
            }
        }
    }

    @Override
    public PostingsFormatProvider postingsFormatProvider() {
        return postingsFormat;
    }

    @Override
    public DocValuesFormatProvider docValuesFormatProvider() {
        return docValuesFormat;
    }

    @Override
    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
        builder.startObject(names.name());
        boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
        doXContentBody(builder, includeDefaults, params);
        return builder.endObject();
    }

    protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {

        builder.field("type", contentType());
        if (includeDefaults || !names.name().equals(names.indexNameClean())) {
            builder.field("index_name", names.indexNameClean());
        }

        if (includeDefaults || boost != 1.0f) {
            builder.field("boost", boost);
        }

        FieldType defaultFieldType = defaultFieldType();
        if (includeDefaults || fieldType.indexed() != defaultFieldType.indexed() ||
                fieldType.tokenized() != defaultFieldType.tokenized()) {
            builder.field("index", indexTokenizeOptionToString(fieldType.indexed(), fieldType.tokenized()));
        }
        if (includeDefaults || fieldType.stored() != defaultFieldType.stored()) {
            builder.field("store", fieldType.stored());
        }
        if (includeDefaults || hasDocValues() != Defaults.DOC_VALUES) {
            builder.field(TypeParsers.DOC_VALUES, docValues);
        }
        if (includeDefaults || fieldType.storeTermVectors() != defaultFieldType.storeTermVectors()) {
            builder.field("term_vector", termVectorOptionsToString(fieldType));
        }
        if (includeDefaults || fieldType.omitNorms() != defaultFieldType.omitNorms() || normsLoading != null) {
            builder.startObject("norms");
            if (includeDefaults || fieldType.omitNorms() != defaultFieldType.omitNorms()) {
                builder.field("enabled", !fieldType.omitNorms());
            }
            if (normsLoading != null) {
                builder.field(Loading.KEY, normsLoading);
            }
            builder.endObject();
        }
        if (includeDefaults || fieldType.indexOptions() != defaultFieldType.indexOptions()) {
            builder.field("index_options", indexOptionToString(fieldType.indexOptions()));
        }

        if (indexAnalyzer == null && searchAnalyzer == null) {
            if (includeDefaults) {
                builder.field("analyzer", "default");
            }
        } else if (indexAnalyzer == null) {
            // searchAnalyzer != null
            if (includeDefaults || (!searchAnalyzer.name().startsWith("_") && !searchAnalyzer.name().equals("default"))) {
                builder.field("search_analyzer", searchAnalyzer.name());
            }
        } else if (searchAnalyzer == null) {
            // indexAnalyzer != null
            if (includeDefaults || (!indexAnalyzer.name().startsWith("_") && !indexAnalyzer.name().equals("default"))) {
                builder.field("index_analyzer", indexAnalyzer.name());
            }
        } else if (indexAnalyzer.name().equals(searchAnalyzer.name())) {
            // indexAnalyzer == searchAnalyzer
            if (includeDefaults || (!indexAnalyzer.name().startsWith("_") && !indexAnalyzer.name().equals("default"))) {
                builder.field("analyzer", indexAnalyzer.name());
            }
        } else {
            // both are there but different
            if (includeDefaults || (!indexAnalyzer.name().startsWith("_") && !indexAnalyzer.name().equals("default"))) {
                builder.field("index_analyzer", indexAnalyzer.name());
            }
            if (includeDefaults || (!searchAnalyzer.name().startsWith("_") && !searchAnalyzer.name().equals("default"))) {
                builder.field("search_analyzer", searchAnalyzer.name());
            }
        }

        if (postingsFormat != null) {
            if (includeDefaults || !postingsFormat.name().equals(defaultPostingFormat())) {
                builder.field("postings_format", postingsFormat.name());
            }
        } else if (includeDefaults) {
            String format = defaultPostingFormat();
            if (format == null) {
                format = PostingsFormatService.DEFAULT_FORMAT;
            }
            builder.field("postings_format", format);
        }

        if (docValuesFormat != null) {
            if (includeDefaults || !docValuesFormat.name().equals(defaultDocValuesFormat())) {
                builder.field(DOC_VALUES_FORMAT, docValuesFormat.name());
            }
        } else if (includeDefaults) {
            String format = defaultDocValuesFormat();
            if (format == null) {
                format = DocValuesFormatService.DEFAULT_FORMAT;
            }
            builder.field(DOC_VALUES_FORMAT, format);
        }

        if (similarity() != null) {
            builder.field("similarity", similarity().name());
        } else if (includeDefaults) {
            builder.field("similariry", SimilarityLookupService.DEFAULT_SIMILARITY);
        }

        if (customFieldDataSettings != null) {
            builder.field("fielddata", (Map) customFieldDataSettings.getAsMap());
        } else if (includeDefaults) {
            builder.field("fielddata", (Map) fieldDataType.getSettings().getAsMap());
        }
        multiFields.toXContent(builder, params);

        if (copyTo != null) {
            copyTo.toXContent(builder, params);
        }
    }

    protected static String indexOptionToString(IndexOptions indexOption) {
        switch (indexOption) {
            case DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS:
                return TypeParsers.INDEX_OPTIONS_OFFSETS;
            case DOCS_AND_FREQS:
                return TypeParsers.INDEX_OPTIONS_FREQS;
            case DOCS_AND_FREQS_AND_POSITIONS:
                return TypeParsers.INDEX_OPTIONS_POSITIONS;
            case DOCS_ONLY:
                return TypeParsers.INDEX_OPTIONS_DOCS;
            default:
                throw new ElasticsearchIllegalArgumentException("Unknown IndexOptions [" + indexOption + "]");
        }
    }

    public static String termVectorOptionsToString(FieldType fieldType) {
        if (!fieldType.storeTermVectors()) {
            return "no";
        } else if (!fieldType.storeTermVectorOffsets() && !fieldType.storeTermVectorPositions()) {
            return "yes";
        } else if (fieldType.storeTermVectorOffsets() && !fieldType.storeTermVectorPositions()) {
            return "with_offsets";
        } else {
            StringBuilder builder = new StringBuilder("with");
            if (fieldType.storeTermVectorPositions()) {
                builder.append("_positions");
            }
            if (fieldType.storeTermVectorOffsets()) {
                builder.append("_offsets");
            }
            if (fieldType.storeTermVectorPayloads()) {
                builder.append("_payloads");
            }
            return builder.toString();
        }
    }

    protected static String indexTokenizeOptionToString(boolean indexed, boolean tokenized) {
        if (!indexed) {
            return "no";
        } else if (tokenized) {
            return "analyzed";
        } else {
            return "not_analyzed";
        }
    }

    protected abstract String contentType();

    @Override
    public void close() {
        multiFields.close();
    }

    @Override
    public boolean isNumeric() {
        return false;
    }

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

    public boolean hasDocValues() {
        return docValues;
    }

    @Override
    public Loading normsLoading(Loading defaultLoading) {
        return normsLoading == null ? defaultLoading : normsLoading;
    }

    public static class MultiFields {

        public static MultiFields empty() {
            return new MultiFields(Defaults.PATH_TYPE, ImmutableOpenMap.<String, Mapper>of());
        }

        public static class Builder {

            private final ImmutableOpenMap.Builder<String, Mapper.Builder> mapperBuilders = ImmutableOpenMap.builder();
            private ContentPath.Type pathType = Defaults.PATH_TYPE;

            public Builder pathType(ContentPath.Type pathType) {
                this.pathType = pathType;
                return this;
            }

            public Builder add(Mapper.Builder builder) {
                mapperBuilders.put(builder.name(), builder);
                return this;
            }

            @SuppressWarnings("unchecked")
            public MultiFields build(AbstractFieldMapper.Builder mainFieldBuilder, BuilderContext context) {
                if (pathType == Defaults.PATH_TYPE && mapperBuilders.isEmpty()) {
                    return empty();
                } else if (mapperBuilders.isEmpty()) {
                    return new MultiFields(pathType, ImmutableOpenMap.<String, Mapper>of());
                } else {
                    ContentPath.Type origPathType = context.path().pathType();
                    context.path().pathType(pathType);
                    context.path().add(mainFieldBuilder.name());
                    ImmutableOpenMap.Builder mapperBuilders = this.mapperBuilders;
                    for (ObjectObjectCursor<String, Mapper.Builder> cursor : this.mapperBuilders) {
                        String key = cursor.key;
                        Mapper.Builder value = cursor.value;
                        mapperBuilders.put(key, value.build(context));
                    }
                    context.path().remove();
                    context.path().pathType(origPathType);
                    ImmutableOpenMap.Builder<String, Mapper> mappers = mapperBuilders.cast();
                    return new MultiFields(pathType, mappers.build());
                }
            }

        }

        private final ContentPath.Type pathType;
        private volatile ImmutableOpenMap<String, Mapper> mappers;

        public MultiFields(ContentPath.Type pathType, ImmutableOpenMap<String, Mapper> mappers) {
            this.pathType = pathType;
            this.mappers = mappers;
            // we disable the all in multi-field mappers
            for (ObjectCursor<Mapper> cursor : mappers.values()) {
                Mapper mapper = cursor.value;
                if (mapper instanceof AllFieldMapper.IncludeInAll) {
                    ((AllFieldMapper.IncludeInAll) mapper).unsetIncludeInAll();
                }
            }
        }

        public void parse(AbstractFieldMapper mainField, ParseContext context) throws IOException {
            if (mappers.isEmpty()) {
                return;
            }

            context.setWithinMultiFields();

            ContentPath.Type origPathType = context.path().pathType();
            context.path().pathType(pathType);

            context.path().add(mainField.name());
            for (ObjectCursor<Mapper> cursor : mappers.values()) {
                cursor.value.parse(context);
            }
            context.path().remove();
            context.path().pathType(origPathType);

            context.clearWithinMultiFields();
        }

        // No need for locking, because locking is taken care of in ObjectMapper#merge and DocumentMapper#merge
        public void merge(Mapper mergeWith, MergeContext mergeContext) throws MergeMappingException {
            AbstractFieldMapper mergeWithMultiField = (AbstractFieldMapper) mergeWith;

            List<FieldMapper> newFieldMappers = null;
            ImmutableOpenMap.Builder<String, Mapper> newMappersBuilder = null;

            for (ObjectCursor<Mapper> cursor : mergeWithMultiField.multiFields.mappers.values()) {
                Mapper mergeWithMapper = cursor.value;
                Mapper mergeIntoMapper = mappers.get(mergeWithMapper.name());
                if (mergeIntoMapper == null) {
                    // no mapping, simply add it if not simulating
                    if (!mergeContext.mergeFlags().simulate()) {
                        // we disable the all in multi-field mappers
                        if (mergeWithMapper instanceof AllFieldMapper.IncludeInAll) {
                            ((AllFieldMapper.IncludeInAll) mergeWithMapper).unsetIncludeInAll();
                        }
                        if (newMappersBuilder == null) {
                            newMappersBuilder = ImmutableOpenMap.builder(mappers);
                        }
                        newMappersBuilder.put(mergeWithMapper.name(), mergeWithMapper);
                        if (mergeWithMapper instanceof AbstractFieldMapper) {
                            if (newFieldMappers == null) {
                                newFieldMappers = new ArrayList<>(2);
                            }
                            newFieldMappers.add((FieldMapper) mergeWithMapper);
                        }
                    }
                } else {
                    mergeIntoMapper.merge(mergeWithMapper, mergeContext);
                }
            }

            // first add all field mappers
            if (newFieldMappers != null) {
                mergeContext.docMapper().addFieldMappers(newFieldMappers);
            }
            // now publish mappers
            if (newMappersBuilder != null) {
                mappers = newMappersBuilder.build();
            }
        }

        public void traverse(FieldMapperListener fieldMapperListener) {
            for (ObjectCursor<Mapper> cursor : mappers.values()) {
                cursor.value.traverse(fieldMapperListener);
            }
        }

        public void close() {
            for (ObjectCursor<Mapper> cursor : mappers.values()) {
                cursor.value.close();
            }
        }

        public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
            if (pathType != Defaults.PATH_TYPE) {
                builder.field("path", pathType.name().toLowerCase(Locale.ROOT));
            }
            if (!mappers.isEmpty()) {
                builder.startObject("fields");
                for (ObjectCursor<Mapper> cursor : mappers.values()) {
                    cursor.value.toXContent(builder, params);
                }
                builder.endObject();
            }
            return builder;
        }
    }

    /**
     * Represents a list of fields with optional boost factor where the current field should be copied to
     */
    public static class CopyTo {

        private final ImmutableList<String> copyToFields;

        private CopyTo(ImmutableList<String> copyToFields) {
            this.copyToFields = copyToFields;
        }

        /**
         * Creates instances of the fields that the current field should be copied to
         */
        public void parse(ParseContext context) throws IOException {
            if (!context.isWithinCopyTo()) {
                for (String field : copyToFields) {
                    parse(field, context);
                }
            }
        }

        public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
            if (!copyToFields.isEmpty()) {
                builder.startArray("copy_to");
                for (String field : copyToFields) {
                    builder.value(field);
                }
                builder.endArray();
            }
            return builder;
        }

        public static class Builder {
            private final ImmutableList.Builder<String> copyToBuilders = ImmutableList.builder();

            public Builder add(String field) {
                copyToBuilders.add(field);
                return this;
            }

            public CopyTo build() {
                return new CopyTo(copyToBuilders.build());
            }
        }

        public ImmutableList<String> copyToFields() {
            return copyToFields;
        }

        /**
         * Creates an copy of the current field with given field name and boost
         */
        public void parse(String field, ParseContext context) throws IOException {
            context.setWithinCopyTo();
            FieldMappers mappers = context.docMapper().mappers().indexName(field);
            if (mappers != null && !mappers.isEmpty()) {
                mappers.mapper().parse(context);
            } else {
                int posDot = field.lastIndexOf('.');
                if (posDot > 0) {
                    // Compound name
                    String objectPath = field.substring(0, posDot);
                    String fieldPath = field.substring(posDot + 1);
                    ObjectMapper mapper = context.docMapper().objectMappers().get(objectPath);
                    if (mapper == null) {
                        //TODO: Create an object dynamically?
                        throw new MapperParsingException("attempt to copy value to non-existing object [" + field + "]");
                    }

                    ContentPath.Type origPathType = context.path().pathType();
                    context.path().pathType(ContentPath.Type.FULL);
                    context.path().add(objectPath);

                    // We might be in dynamically created field already, so need to clean withinNewMapper flag
                    // and then restore it, so we wouldn't miss new mappers created from copy_to fields
                    boolean origWithinNewMapper = context.isWithinNewMapper();
                    context.clearWithinNewMapper();

                    try {
                        mapper.parseDynamicValue(context, fieldPath, context.parser().currentToken());
                    } finally {
                        if (origWithinNewMapper) {
                            context.setWithinNewMapper();
                        } else {
                            context.clearWithinNewMapper();
                        }
                        context.path().remove();
                        context.path().pathType(origPathType);
                    }

                } else {
                    // We might be in dynamically created field already, so need to clean withinNewMapper flag
                    // and then restore it, so we wouldn't miss new mappers created from copy_to fields
                    boolean origWithinNewMapper = context.isWithinNewMapper();
                    context.clearWithinNewMapper();
                    try {
                        context.docMapper().root().parseDynamicValue(context, field, context.parser().currentToken());
                    } finally {
                        if (origWithinNewMapper) {
                            context.setWithinNewMapper();
                        } else {
                            context.clearWithinNewMapper();
                        }
                    }

                }
            }
            context.clearWithinCopyTo();
        }

    }

}


text:
using System;
using System.Collections.Generic;
using InspectionCrawler.Domain.Model;

namespace InspectionCrawler.Domain.Extensions
{
    public static class PageExtensions
    {
        public static IEnumerable<Uri> GetExternalLinks(this Page page)
        {
            var host = page.Uri.Host;

            var externalUris = new HashSet<Uri>();

            foreach (var link in page.Examiner.Links)
            {
                var scheme = link.Scheme;
                if (!(scheme.Equals(Uri.UriSchemeHttp) || scheme.Equals(Uri.UriSchemeHttps)))
                    continue;

                if (!link.Host.Equals(host))
                    externalUris.Add(link);
            }

            return externalUris;
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
package org.camunda.bpm.engine.impl.cmd;

import java.util.Collection;
import java.util.Map;

import org.camunda.bpm.engine.impl.interceptor.CommandContext;
import org.camunda.bpm.engine.impl.persistence.entity.PropertyChange;

/**
 * Patches execution variables: First, applies modifications to existing variables and then deletes
 * specified variables.
 *
 * @author Thorben Lindhauer
 *
 */
public class PatchExecutionVariablesCmd extends AbstractPatchVariablesCmd {

  private static final long serialVersionUID = 1L;

  public PatchExecutionVariablesCmd(String executionId, Map<String, ? extends Object> modifications, Collection<String> deletions, boolean isLocal) {
    super(executionId, modifications, deletions, isLocal);
  }

  protected SetExecutionVariablesCmd getSetVariableCmd() {
    return new SetExecutionVariablesCmd(entityId, variables, isLocal);
  }

  protected RemoveExecutionVariablesCmd getRemoveVariableCmd() {
    return new RemoveExecutionVariablesCmd(entityId, deletions, isLocal);
  }

  public void logVariableOperation(CommandContext commandContext) {
    commandContext.getOperationLogManager().logVariableOperation(getLogEntryOperation(), entityId, null,
      PropertyChange.EMPTY_CHANGE);
  }
}


text:
SVNLockFrameRangeDialog::SVNLockFrameRangeDialog(QWidget *parent,
												 const QString &workingDir, const QString &file, int frameCount)
	: Dialog(TApp::instance()->getMainWindow(), true, false), m_workingDir(workingDir), m_file(file), m_hasError(false), m_fromIsValid(true), m_toIsValid(true)
{
	setModal(false);
	setAttribute(Qt::WA_DeleteOnClose, true);

	setWindowTitle(tr("Version Control: Edit Frame Range"));

	setMinimumSize(300, 220);
	QWidget *container = new QWidget;

	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->setAlignment(Qt::AlignHCenter);
	mainLayout->setMargin(0);

	QHBoxLayout *hLayout = new QHBoxLayout;

	m_waitingLabel = new QLabel;
	QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
	waitingMove->setParent(this);

	m_waitingLabel->setMovie(waitingMove);
	waitingMove->setCacheMode(QMovie::CacheAll);
	waitingMove->start();

	m_textLabel = new QLabel;

	m_textLabel->setText(tr("Temporary Lock file..."));

	hLayout->addStretch();
	hLayout->addWidget(m_waitingLabel);
	hLayout->addWidget(m_textLabel);
	hLayout->addStretch();

	mainLayout->addLayout(hLayout);
	mainLayout->addSpacing(10);

	QHBoxLayout *fromToLayout = new QHBoxLayout;

	m_fromLabel = new QLabel(tr("From:"));
	m_fromLabel->setMaximumWidth(60);
	m_fromLabel->hide();

	m_toLabel = new QLabel(tr("To:"));
	m_toLabel->setMaximumWidth(60);
	m_toLabel->hide();

	m_fromLineEdit = new DVGui::IntLineEdit;
	m_fromLineEdit->setRange(1, frameCount);
	m_fromLineEdit->hide();
	connect(m_fromLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(onFromLineEditTextChanged()));

	m_toLineEdit = new DVGui::IntLineEdit;
	m_toLineEdit->setRange(1, frameCount);
	m_toLineEdit->hide();
	m_toLineEdit->setValue(frameCount);
	connect(m_toLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(onToLineEditTextChanged()));

	fromToLayout->addStretch();
	fromToLayout->addWidget(m_fromLabel);
	fromToLayout->addWidget(m_fromLineEdit);
	fromToLayout->addWidget(m_toLabel);
	fromToLayout->addWidget(m_toLineEdit);
	fromToLayout->addStretch();

	mainLayout->addLayout(fromToLayout);

	QHBoxLayout *commentLayout = new QHBoxLayout;

	m_commentTextEdit = new QPlainTextEdit;
	m_commentTextEdit->setMaximumHeight(50);
	m_commentTextEdit->hide();

	m_commentLabel = new QLabel(tr("Comment:"));
	m_commentLabel->setFixedWidth(55);
	m_commentLabel->hide();

	commentLayout->addWidget(m_commentLabel);
	commentLayout->addWidget(m_commentTextEdit);

	mainLayout->addLayout(commentLayout);

	container->setLayout(mainLayout);

	beginHLayout();
	addWidget(container, false);
	endHLayout();

	m_lockButton = new QPushButton(tr("Edit"));
	connect(m_lockButton, SIGNAL(clicked()), this, SLOT(onLockButtonClicked()));

	m_cancelButton = new QPushButton(tr("Cancel"));
	connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(onCancelButtonClicked()));

	addButtonBarWidget(m_lockButton, m_cancelButton);

	// 0. Connect for svn errors (that may occurs)
	connect(&m_thread, SIGNAL(error(const QString &)), this, SLOT(onError(const QString &)));

	// Step 1: Lock
	QStringList args;
	args << "lock";
	args << m_file;

	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onLockDone()));
	m_thread.executeCommand(m_workingDir, "svn", args, false);
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::switchToCloseButton()
{
	m_waitingLabel->hide();
	m_commentTextEdit->hide();
	m_commentLabel->hide();
	m_lockButton->disconnect();
	m_lockButton->setText("Close");
	m_lockButton->setEnabled(true);
	m_cancelButton->hide();
	connect(m_lockButton, SIGNAL(clicked()), this, SLOT(close()));
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::onError(const QString &errorString)
{
	m_textLabel->setText(errorString);
	switchToCloseButton();
	update();
	m_hasError = true;
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::onPropGetDone(const QString &xmlResponse)
{
	SVNPartialLockReader reader(xmlResponse);
	QList<SVNPartialLock> lockList = reader.getPartialLock();
	if (lockList.isEmpty())
		m_textLabel->setText(tr("No frame range edited."));
	else {
		m_lockInfos = lockList.at(0).m_partialLockList;
		if (m_lockInfos.isEmpty())
			m_textLabel->setText(tr("No frame range edited."));
		else {
			QString temp;
			for (int i = 0; i < m_lockInfos.size(); i++) {
				if (i != 0)
					temp.append("\n\n");
				SVNPartialLockInfo lock = m_lockInfos.at(i);
				temp.append(tr("%1 on %2 is editing frames from %3 to %4.").arg(lock.m_userName).arg(lock.m_hostName).arg(lock.m_from).arg(lock.m_to));
			}
			m_textLabel->setText(temp);
		}
	}

	m_lockButton->show();

	m_cancelButton->show();

	// Update from and to lineedit valid status
	onFromLineEditTextChanged();
	onToLineEditTextChanged();

	m_waitingLabel->hide();

	m_fromLabel->show();
	m_toLabel->show();
	m_fromLineEdit->show();
	m_toLineEdit->show();

	m_commentLabel->show();
	m_commentTextEdit->show();
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::onLockButtonClicked()
{
	// Build the old partial Lock string
	QString partialLockString;

	int count = m_lockInfos.size();
	for (int i = 0; i < count; i++) {
		if (i != 0)
			partialLockString.append(";");
		SVNPartialLockInfo lockInfo = m_lockInfos.at(i);
		partialLockString.append(lockInfo.m_userName + "@" + lockInfo.m_hostName + ":" +
								 QString::number(lockInfo.m_from) + ":" +
								 QString::number(lockInfo.m_to));
	}

	// Add the new value
	QString userName = VersionControl::instance()->getUserName();
	QString hostName = QHostInfo::localHostName();
	QString from = QString::number(m_fromLineEdit->getValue());
	QString to = QString::number(m_toLineEdit->getValue());

	if (count != 0)
		partialLockString.append(";");
	partialLockString.append(userName + "@" + hostName + ":" + from + ":" + to);

	// Step 3: propset
	QStringList args;
	args << "propset";
	args << "partial-lock";
	args << partialLockString;
	args << m_file;

	m_thread.disconnect(SIGNAL(done(const QString &)));
	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onPropSetDone()));
	m_thread.executeCommand(m_workingDir, "svn", args, true);
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::onCancelButtonClicked()
{
	QStringList args;
	args << "unlock";
	args << m_file;

	m_thread.disconnect(SIGNAL(done(const QString &)));
	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(close()));
	m_thread.executeCommand(m_workingDir, "svn", args, true);
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::onFromLineEditTextChanged()
{
	int value = m_fromLineEdit->getValue();

	// Check if from is inside one range
	int count = m_lockInfos.size();

	m_fromIsValid = true;
	for (int i = 0; i < count; i++) {
		SVNPartialLockInfo lockInfo = m_lockInfos.at(i);
		if (value >= lockInfo.m_from && value <= lockInfo.m_to) {
			m_fromIsValid = false;
			break;
		}
	}

	m_fromLineEdit->setStyleSheet(m_fromIsValid ? "" : "color: red; background-color: red;");
	m_lockButton->setEnabled(m_fromIsValid && m_toIsValid);
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::onToLineEditTextChanged()
{
	int value = m_toLineEdit->getValue();

	// Check if from is inside one range
	int count = m_lockInfos.size();
	m_toIsValid = true;
	for (int i = 0; i < count; i++) {
		SVNPartialLockInfo lockInfo = m_lockInfos.at(i);
		if (value >= lockInfo.m_from && value <= lockInfo.m_to) {
			m_toIsValid = false;
			break;
		}
	}

	m_toLineEdit->setStyleSheet(m_toIsValid ? "" : "color: red; background-color: red;");
	m_lockButton->setEnabled(m_fromIsValid && m_toIsValid);
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::onLockDone()
{
	if (!m_hasError) {
		m_textLabel->setText(tr("Getting frame range edit information..."));

		// Step 2: propget
		QStringList args;
		args << "propget";
		args << "partial-lock";
		args << m_file;
		args << "--xml";

		m_thread.disconnect(SIGNAL(done(const QString &)));
		connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onPropGetDone(const QString &)));
		m_thread.executeCommand(m_workingDir, "svn", args, true);
	}
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::onPropSetDone()
{
	// Step 4: Commit
	QStringList args;
	args << "commit";
	args << m_file;
	if (!m_commentTextEdit->toPlainText().isEmpty())
		args << QString("-m").append(m_commentTextEdit->toPlainText());
	else
		args << QString("-m").append(VersionControl::instance()->getUserName() + " edit frame range.");
	m_thread.disconnect(SIGNAL(done(const QString &)));
	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(finish()));
	m_thread.executeCommand(m_workingDir, "svn", args, true);
}

//-----------------------------------------------------------------------------

void SVNLockFrameRangeDialog::finish()
{
	if (!m_hasError) {
		emit done(QStringList(m_file));
		close();
	}
}

//=============================================================================
// SVNLockMultiFrameRangeDialog
//-----------------------------------------------------------------------------

SVNLockMultiFrameRangeDialog::SVNLockMultiFrameRangeDialog(QWidget *parent,
														   const QString &workingDir,
														   const QStringList &files)
	: Dialog(TApp::instance()->getMainWindow(), true, false), m_workingDir(workingDir), m_files(files), m_hasError(false), m_fromIsValid(true), m_toIsValid(true)
{
	setModal(false);
	setAttribute(Qt::WA_DeleteOnClose, true);

	setWindowTitle(tr("Version Control: Edit Frame Range"));

	setMinimumSize(300, 220);
	QWidget *container = new QWidget;

	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->setAlignment(Qt::AlignHCenter);
	mainLayout->setMargin(0);

	QHBoxLayout *hLayout = new QHBoxLayout;

	m_waitingLabel = new QLabel;
	QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
	waitingMove->setParent(this);

	m_waitingLabel->setMovie(waitingMove);
	waitingMove->setCacheMode(QMovie::CacheAll);
	waitingMove->start();

	m_textLabel = new QLabel;

	m_textLabel->setText(tr("Getting repository status..."));

	hLayout->addStretch();
	hLayout->addWidget(m_waitingLabel);
	hLayout->addWidget(m_textLabel);
	hLayout->addStretch();

	mainLayout->addLayout(hLayout);
	mainLayout->addSpacing(10);

	QHBoxLayout *fromToLayout = new QHBoxLayout;

	m_fromLabel = new QLabel(tr("From:"));
	m_fromLabel->setMaximumWidth(60);
	m_fromLabel->hide();

	m_toLabel = new QLabel(tr("To:"));
	m_toLabel->setMaximumWidth(60);
	m_toLabel->hide();

	int frameCount = m_files.size();

	m_fromLineEdit = new DVGui::IntLineEdit;
	m_fromLineEdit->setRange(1, frameCount);
	m_fromLineEdit->hide();
	connect(m_fromLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(onFromLineEditTextChanged()));

	m_toLineEdit = new DVGui::IntLineEdit;
	m_toLineEdit->setRange(1, frameCount);
	m_toLineEdit->hide();
	m_toLineEdit->setValue(frameCount);
	connect(m_toLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(onToLineEditTextChanged()));

	fromToLayout->addStretch();
	fromToLayout->addWidget(m_fromLabel);
	fromToLayout->addWidget(m_fromLineEdit);
	fromToLayout->addWidget(m_toLabel);
	fromToLayout->addWidget(m_toLineEdit);
	fromToLayout->addStretch();

	mainLayout->addLayout(fromToLayout);

	QHBoxLayout *commentLayout = new QHBoxLayout;

	m_commentTextEdit = new QPlainTextEdit;
	m_commentTextEdit->setMaximumHeight(50);
	m_commentTextEdit->hide();

	m_commentLabel = new QLabel(tr("Comment:"));
	m_commentLabel->setFixedWidth(55);
	m_commentLabel->hide();

	commentLayout->addWidget(m_commentLabel);
	commentLayout->addWidget(m_commentTextEdit);

	mainLayout->addLayout(commentLayout);

	container->setLayout(mainLayout);

	beginHLayout();
	addWidget(container, false);
	endHLayout();

	m_lockButton = new QPushButton(tr("Edit"));
	connect(m_lockButton, SIGNAL(clicked()), this, SLOT(onLockButtonClicked()));

	m_cancelButton = new QPushButton(tr("Cancel"));
	connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(reject()));

	m_lockButton->hide();
	m_cancelButton->hide();

	addButtonBarWidget(m_lockButton, m_cancelButton);

	// 0. Connect for svn errors (that may occurs)
	connect(&m_thread, SIGNAL(error(const QString &)), this, SLOT(onError(const QString &)));

	// 1. Getting status
	connect(&m_thread, SIGNAL(statusRetrieved(const QString &)), this, SLOT(onStatusRetrieved(const QString &)));
	m_thread.getSVNStatus(m_workingDir, m_files, true);
}

//-----------------------------------------------------------------------------

void SVNLockMultiFrameRangeDialog::switchToCloseButton()
{
	m_waitingLabel->hide();
	m_commentTextEdit->hide();
	m_commentLabel->hide();
	m_lockButton->disconnect();
	m_lockButton->setText("Close");
	m_lockButton->setEnabled(true);
	m_cancelButton->hide();
	connect(m_lockButton, SIGNAL(clicked()), this, SLOT(close()));
}

//-----------------------------------------------------------------------------

void SVNLockMultiFrameRangeDialog::onError(const QString &errorString)
{
	m_textLabel->setText(errorString);
	switchToCloseButton();
	update();
	m_hasError = true;
}

//-----------------------------------------------------------------------------

void SVNLockMultiFrameRangeDialog::onStatusRetrieved(const QString &xmlResponse)
{
	m_waitingLabel->hide();

	SVNStatusReader sr(xmlResponse);
	m_status = sr.getStatus();

	// Fill m_lockInfos list
	SVNPartialLockInfo info;
	info.m_from = 0;
	int count = m_status.size();
	for (int i = 0; i < count; i++) {
		SVNStatus s = m_status.at(i);
		if (s.m_isLocked) {
			if (info.m_userName != s.m_lockOwner && info.m_userName != "") {
				m_lockInfos.append(info);
				info.m_from = 0;
			}
			info.m_userName = s.m_lockOwner;
			if (info.m_from == 0)
				info.m_from = i + 1;
			else
				info.m_to = i + 1;
		}
	}

	if (info.m_userName != "" && info.m_from != 0)
		m_lockInfos.append(info);

	if (m_lockInfos.isEmpty())
		m_textLabel->setText(tr("No frame range edited."));
	else {
		QString temp;
		for (int i = 0; i < m_lockInfos.size(); i++) {
			if (i != 0)
				temp.append("\n\n");
			SVNPartialLockInfo lock = m_lockInfos.at(i);
			temp.append(tr("%1 is editing frames from %2 to %3").arg(lock.m_userName).arg(lock.m_from).arg(lock.m_to));
		}
		m_textLabel->setText(temp);
	}

	m_lockButton->show();

	m_cancelButton->show();

	// Update from and to lineedit valid status
	onFromLineEditTextChanged();
	onToLineEditTextChanged();

	m_waitingLabel->hide();

	m_fromLabel->show();
	m_toLabel->show();
	m_fromLineEdit->show();
	m_toLineEdit->show();

	m_commentLabel->show();
	m_commentTextEdit->show();
}
//-----------------------------------------------------------------------------

void SVNLockMultiFrameRangeDialog::onFromLineEditTextChanged()
{
	int value = m_fromLineEdit->getValue();

	// Check if from is inside one range
	int count = m_lockInfos.size();

	m_fromIsValid = true;
	for (int i = 0; i < count; i++) {
		SVNPartialLockInfo lockInfo = m_lockInfos.at(i);
		if (value >= lockInfo.m_from && value <= lockInfo.m_to) {
			m_fromIsValid = false;
			break;
		}
	}

	m_fromLineEdit->setStyleSheet(m_fromIsValid ? "" : "color: red; background-color: red;");
	m_lockButton->setEnabled(m_fromIsValid && m_toIsValid);
}

//-----------------------------------------------------------------------------

void SVNLockMultiFrameRangeDialog::onToLineEditTextChanged()
{
	int value = m_toLineEdit->getValue();

	// Check if from is inside one range
	int count = m_lockInfos.size();
	m_toIsValid = true;
	for (int i = 0; i < count; i++) {
		SVNPartialLockInfo lockInfo = m_lockInfos.at(i);
		if (value >= lockInfo.m_from && value <= lockInfo.m_to) {
			m_toIsValid = false;
			break;
		}
	}

	m_toLineEdit->setStyleSheet(m_toIsValid ? "" : "color: red; background-color: red;");
	m_lockButton->setEnabled(m_fromIsValid && m_toIsValid);
}

//-----------------------------------------------------------------------------

void SVNLockMultiFrameRangeDialog::onLockButtonClicked()
{
	for (int i = m_fromLineEdit->getValue() - 1; i < m_toLineEdit->getValue(); i++)
		m_filesToLock.append(m_files.at(i));

	m_waitingLabel->show();
	m_fromLabel->hide();
	m_toLabel->hide();
	m_fromLineEdit->hide();
	m_toLineEdit->hide();
	m_commentLabel->hide();
	m_commentTextEdit->hide();

	m_textLabel->setText(tr("Editing %1 items...").arg(m_filesToLock.size()));

	QStringList args;
	args << "lock";

	int fileCount = m_filesToLock.size();
	for (int i = 0; i < fileCount; i++)
		args << m_filesToLock.at(i);

	if (!m_commentTextEdit->toPlainText().isEmpty())
		args << QString("-m").append(m_commentTextEdit->toPlainText());
	else
		args << QString("-m").append(VersionControl::instance()->getUserName() + " edit frame range.");
	m_thread.disconnect(SIGNAL(done(const QString &)));
	connect(&m_thread, SIGNAL(done(const QString &)), SLOT(onLockDone()));
	m_thread.executeCommand(m_workingDir, "svn", args);
}

//-----------------------------------------------------------------------------

void SVNLockMultiFrameRangeDialog::onLockDone()
{
	if (!m_hasError) {
		QStringList files;
		int fileCount = m_files.size();
		for (int i = 0; i < fileCount; i++)
			files.append(m_files.at(i));
		emit done(files);
		close();
	}
}

//=============================================================================
// SVNUnlockFrameRangeDialog
//-----------------------------------------------------------------------------

SVNUnlockFrameRangeDialog::SVNUnlockFrameRangeDialog(QWidget *parent,
													 const QString &workingDir, const QString &file)
	: Dialog(TApp::instance()->getMainWindow(), true, false), m_workingDir(workingDir), m_file(file), m_hasError(false)
{
	setModal(false);
	setAttribute(Qt::WA_DeleteOnClose, true);

	setWindowTitle(tr("Version Control: Unlock Frame Range"));

	setMinimumSize(300, 150);
	QWidget *container = new QWidget;

	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->setAlignment(Qt::AlignHCenter);
	mainLayout->setMargin(0);

	QHBoxLayout *hLayout = new QHBoxLayout;

	m_waitingLabel = new QLabel;
	QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
	waitingMove->setParent(this);

	m_waitingLabel->hide();

	m_waitingLabel->setMovie(waitingMove);
	waitingMove->setCacheMode(QMovie::CacheAll);
	waitingMove->start();

	m_textLabel = new QLabel;

	m_textLabel->setText(tr("Note: the file will be updated too. Are you sure ?"));

	hLayout->addStretch();
	hLayout->addWidget(m_waitingLabel);
	hLayout->addWidget(m_textLabel);
	hLayout->addStretch();

	mainLayout->addLayout(hLayout);
	container->setLayout(mainLayout);

	beginHLayout();
	addWidget(container, false);
	endHLayout();

	m_unlockButton = new QPushButton(tr("Unlock"));
	connect(m_unlockButton, SIGNAL(clicked()), this, SLOT(onUnlockButtonClicked()));

	m_cancelButton = new QPushButton(tr("Cancel"));
	connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(reject()));

	addButtonBarWidget(m_unlockButton, m_cancelButton);

	// 0. Connect for svn errors (that may occurs)
	connect(&m_thread, SIGNAL(error(const QString &)), this, SLOT(onError(const QString &)));
}

//-----------------------------------------------------------------------------

void SVNUnlockFrameRangeDialog::onCommitDone()
{
	m_textLabel->setText(tr("Unlock done successfully."));

	QStringList files;
	files.append(m_file);
	emit done(files);
	switchToCloseButton();
}

//-----------------------------------------------------------------------------

void SVNUnlockFrameRangeDialog::onUpdateDone()
{
	m_textLabel->setText(tr("Locking file..."));

	// Step 2: Lock
	QStringList args;
	args << "lock";
	args << m_file;

	m_thread.disconnect(SIGNAL(done(const QString &)));
	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onLockDone()));
	m_thread.executeCommand(m_workingDir, "svn", args, false);
}

//-----------------------------------------------------------------------------

void SVNUnlockFrameRangeDialog::onLockDone()
{
	m_textLabel->setText(tr("Getting frame range edit information..."));

	// Step 3: propget
	QStringList args;
	args << "propget";
	args << "partial-lock";
	args << m_file;
	args << "--xml";

	m_thread.disconnect(SIGNAL(done(const QString &)));
	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onPropGetDone(const QString &)));
	m_thread.executeCommand(m_workingDir, "svn", args, true);
}

//-----------------------------------------------------------------------------

void SVNUnlockFrameRangeDialog::onError(const QString &text)
{
	m_textLabel->setText(text);
	switchToCloseButton();
	update();
	m_hasError = true;
}

//-----------------------------------------------------------------------------

void SVNUnlockFrameRangeDialog::onPropGetDone(const QString &xmlResponse)
{
	SVNPartialLockReader reader(xmlResponse);
	QList<SVNPartialLock> lockList = reader.getPartialLock();
	if (lockList.isEmpty()) {
		m_textLabel->setText(tr("No frame range edited."));
		switchToCloseButton();
		return;
	} else {
		m_lockInfos = lockList.at(0).m_partialLockList;
		if (m_lockInfos.isEmpty()) {
			m_textLabel->setText(tr("No frame range edited."));
			switchToCloseButton();
			return;
		}
	}

	QString partialLockString;

	QString userName = VersionControl::instance()->getUserName();
	QString hostName = QHostInfo::localHostName();

	int count = m_lockInfos.size();

	int entryAdded = 0;
	for (int i = 0; i < count; i++) {
		SVNPartialLockInfo lockInfo = m_lockInfos.at(i);
		bool isMe = lockInfo.m_userName == userName && lockInfo.m_hostName == hostName;
		if (!isMe) {
			if (i != 0)
				partialLockString.append(";");
			partialLockString.append(lockInfo.m_userName + "@" + lockInfo.m_hostName + ":" +
									 QString::number(lockInfo.m_from) + ":" +
									 QString::number(lockInfo.m_to));
			entryAdded++;
		} else
			m_myInfo = lockInfo;
	}

	m_textLabel->setText(tr("Updating frame range edit information..."));

	// There is no more partial-lock > propdel
	if (entryAdded == 0) {
		// Step 4: propdel
		QStringList args;
		args << "propdel";
		args << "partial-lock";
		args << m_file;

		m_thread.disconnect(SIGNAL(done(const QString &)));
		connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onPropSetDone()));
		m_thread.executeCommand(m_workingDir, "svn", args, true);
	}
	// Set the partial-lock property
	else {
		// Step 4: propset
		QStringList args;
		args << "propset";
		args << "partial-lock";
		args << partialLockString;
		args << m_file;

		m_thread.disconnect(SIGNAL(done(const QString &)));
		connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onPropSetDone()));
		m_thread.executeCommand(m_workingDir, "svn", args, true);
	}
}

//-----------------------------------------------------------------------------

void SVNUnlockFrameRangeDialog::onPropSetDone()
{
	m_textLabel->setText(tr("Putting changes..."));

	// Step 5: commit
	QStringList args;
	args << "commit";
	args << m_file;
	args << QString("-m").append(m_myInfo.m_userName + " on " + m_myInfo.m_hostName +
								 " unlock frames from " + QString::number(m_myInfo.m_from) + " to " + QString::number(m_myInfo.m_to) + ".");

	m_thread.disconnect(SIGNAL(done(const QString &)));
	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onCommitDone()));
	m_thread.executeCommand(m_workingDir, "svn", args, true);
}

//-----------------------------------------------------------------------------

void SVNUnlockFrameRangeDialog::onUnlockButtonClicked()
{
	m_waitingLabel->show();
	m_textLabel->setText(tr("Updating file..."));

	// Step 1: Update
	QStringList args;
	args << "update";
	args << m_file;

	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onUpdateDone()));
	m_thread.executeCommand(m_workingDir, "svn", args, false);
}

//-----------------------------------------------------------------------------

void SVNUnlockFrameRangeDialog::switchToCloseButton()
{
	m_waitingLabel->hide();
	m_unlockButton->disconnect();
	m_unlockButton->setText(tr("Close"));
	m_unlockButton->setEnabled(true);
	m_unlockButton->show();
	m_cancelButton->hide();
	connect(m_unlockButton, SIGNAL(clicked()), this, SLOT(close()));
}

//=============================================================================
// SVNUnlockMultiFrameRangeDialog
//-----------------------------------------------------------------------------

SVNUnlockMultiFrameRangeDialog::SVNUnlockMultiFrameRangeDialog(QWidget *parent,
															   const QString &workingDir, const QStringList &files)
	: Dialog(TApp::instance()->getMainWindow(), true, false), m_workingDir(workingDir), m_files(files), m_hasError(false)
{
	setModal(false);
	setAttribute(Qt::WA_DeleteOnClose, true);

	setWindowTitle(tr("Version Control: Unlock Frame Range"));

	setMinimumSize(300, 150);
	QWidget *container = new QWidget;

	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->setAlignment(Qt::AlignHCenter);
	mainLayout->setMargin(0);

	QHBoxLayout *hLayout = new QHBoxLayout;

	m_waitingLabel = new QLabel;
	QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
	waitingMove->setParent(this);

	m_waitingLabel->hide();

	m_waitingLabel->setMovie(waitingMove);
	waitingMove->setCacheMode(QMovie::CacheAll);
	waitingMove->start();

	m_textLabel = new QLabel;

	m_textLabel->setText(tr("Getting repository status..."));

	hLayout->addStretch();
	hLayout->addWidget(m_waitingLabel);
	hLayout->addWidget(m_textLabel);
	hLayout->addStretch();

	mainLayout->addLayout(hLayout);
	container->setLayout(mainLayout);

	beginHLayout();
	addWidget(container, false);
	endHLayout();

	m_unlockButton = new QPushButton(tr("Unlock"));
	connect(m_unlockButton, SIGNAL(clicked()), this, SLOT(onUnlockButtonClicked()));

	m_cancelButton = new QPushButton(tr("Cancel"));
	connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(reject()));

	m_unlockButton->hide();

	addButtonBarWidget(m_unlockButton, m_cancelButton);

	// 0. Connect for svn errors (that may occurs)
	connect(&m_thread, SIGNAL(error(const QString &)), this, SLOT(onError(const QString &)));

	// 1. Getting status
	connect(&m_thread, SIGNAL(statusRetrieved(const QString &)), this, SLOT(onStatusRetrieved(const QString &)));
	m_thread.getSVNStatus(m_workingDir, m_files, true);
}
//-----------------------------------------------------------------------------

void SVNUnlockMultiFrameRangeDialog::onUnlockButtonClicked()
{
	m_waitingLabel->show();

	int fileCount = m_filesToUnlock.size();

	m_textLabel->setText(tr("Unlocking %1 items...").arg(fileCount));

	QStringList args;
	args << "unlock";

	for (int i = 0; i < fileCount; i++)
		args << m_filesToUnlock.at(i);

	m_thread.disconnect(SIGNAL(done(const QString &)));
	connect(&m_thread, SIGNAL(done(const QString &)), SLOT(onUnlockDone()));
	m_thread.executeCommand(m_workingDir, "svn", args);
}

//-----------------------------------------------------------------------------

void SVNUnlockMultiFrameRangeDialog::onStatusRetrieved(const QString &xmlResponse)
{
	m_waitingLabel->hide();

	SVNStatusReader sr(xmlResponse);
	m_status = sr.getStatus();

	QString userName = VersionControl::instance()->getUserName();

	int count = m_status.size();
	for (int i = 0; i < count; i++) {
		SVNStatus s = m_status.at(i);
		if (s.m_isLocked && s.m_lockOwner == userName)
			m_filesToUnlock.append(m_files.at(i));
	}

	int filesToUnlockCount = m_filesToUnlock.size();

	if (filesToUnlockCount == 0) {
		m_textLabel->setText(tr("No items to unlock."));
		switchToCloseButton();
	} else {
		m_waitingLabel->hide();
		m_textLabel->setText(tr("%1 items to unlock.").arg(filesToUnlockCount));
		m_unlockButton->show();
	}
}

//-----------------------------------------------------------------------------

void SVNUnlockMultiFrameRangeDialog::onError(const QString &text)
{
	m_textLabel->setText(text);
	switchToCloseButton();
	update();
	m_hasError = true;
}

//-----------------------------------------------------------------------------

void SVNUnlockMultiFrameRangeDialog::switchToCloseButton()
{
	m_waitingLabel->hide();
	m_unlockButton->disconnect();
	m_unlockButton->setText("Close");
	m_unlockButton->setEnabled(true);
	m_unlockButton->show();
	m_cancelButton->hide();
	connect(m_unlockButton, SIGNAL(clicked()), this, SLOT(close()));
}

//-----------------------------------------------------------------------------

void SVNUnlockMultiFrameRangeDialog::onUnlockDone()
{
	if (!m_hasError) {
		QStringList files;
		int fileCount = m_filesToUnlock.size();
		for (int i = 0; i < fileCount; i++)
			files.append(m_filesToUnlock.at(i));
		emit done(files);
		close();
	}
}

//=============================================================================
// SVNFrameRangeLockInfoDialog
//-----------------------------------------------------------------------------

SVNFrameRangeLockInfoDialog::SVNFrameRangeLockInfoDialog(QWidget *parent,
														 const QString &workingDir, const QString &file)
	: Dialog(TApp::instance()->getMainWindow(), true, false), m_workingDir(workingDir), m_file(file)
{
	setModal(false);
	setAttribute(Qt::WA_DeleteOnClose, true);

	setWindowTitle(tr("Version Control: Edit Info"));

	setMinimumSize(300, 150);

	m_waitingLabel = new QLabel;
	QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
	waitingMove->setParent(this);

	m_waitingLabel->setMovie(waitingMove);
	waitingMove->setCacheMode(QMovie::CacheAll);
	waitingMove->start();

	m_textLabel = new QLabel;

	m_textLabel->setText(tr("Getting repository status..."));

	QHBoxLayout *mainLayout = new QHBoxLayout;
	mainLayout->addStretch();
	mainLayout->addWidget(m_waitingLabel);
	mainLayout->addWidget(m_textLabel);
	mainLayout->addStretch();

	beginHLayout();
	addLayout(mainLayout, false);
	endHLayout();

	QPushButton *closeButton = new QPushButton(tr("Close"));
	connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));

	addButtonBarWidget(closeButton);

	// 0. Connect for svn errors (that may occurs)
	connect(&m_thread, SIGNAL(error(const QString &)), this, SLOT(onError(const QString &)));

	// 1. propget
	QStringList args;
	args << "propget";
	args << "partial-lock";
	args << m_file;
	args << "--xml";

	connect(&m_thread, SIGNAL(done(const QString &)), this, SLOT(onPropGetDone(const QString &)));
	m_thread.executeCommand(m_workingDir, "svn", args, true);
}

//-----------------------------------------------------------------------------

void SVNFrameRangeLockInfoDialog::onError(const QString &errorString)
{
	m_waitingLabel->hide();
	m_textLabel->setText(errorString);
}

//-----------------------------------------------------------------------------

void SVNFrameRangeLockInfoDialog::onPropGetDone(const QString &xmlResponse)
{
	m_waitingLabel->hide();

	SVNPartialLockReader reader(xmlResponse);
	QList<SVNPartialLock> lockList = reader.getPartialLock();
	if (lockList.isEmpty())
		m_textLabel->setText(tr("No frame range edited."));
	else {
		QList<SVNPartialLockInfo> lockInfos = lockList.at(0).m_partialLockList;
		if (lockInfos.isEmpty())
			m_textLabel->setText(tr("No frame range edited."));
		else {
			QString temp;
			for (int i = 0; i < lockInfos.size(); i++) {
				if (i != 0)
					temp.append("\n\n");
				SVNPartialLockInfo lock = lockInfos.at(i);
				temp.append(tr("%1 on %2 is editing frames from %3 to %4.").arg(lock.m_userName).arg(lock.m_hostName).arg(lock.m_from).arg(lock.m_to));
			}
			m_textLabel->setText(temp);
		}
	}
}

//=============================================================================
// SVNMultiFrameRangeLockInfoDialog
//-----------------------------------------------------------------------------

SVNMultiFrameRangeLockInfoDialog::SVNMultiFrameRangeLockInfoDialog(QWidget *parent,
																   const QString &workingDir, const QStringList &files)
	: Dialog(TApp::instance()->getMainWindow(), true, false), m_workingDir(workingDir), m_files(files)
{
	setModal(false);
	setAttribute(Qt::WA_DeleteOnClose, true);

	setWindowTitle(tr("Version Control: Edit Info"));

	setMinimumSize(300, 150);

	m_waitingLabel = new QLabel;
	QMovie *waitingMove = new QMovie(":Resources/waiting.gif");
	waitingMove->setParent(this);

	m_waitingLabel->setMovie(waitingMove);
	waitingMove->setCacheMode(QMovie::CacheAll);
	waitingMove->start();

	m_textLabel = new QLabel;

	m_textLabel->setText(tr("Getting repository status..."));

	QHBoxLayout *mainLayout = new QHBoxLayout;
	mainLayout->addStretch();
	mainLayout->addWidget(m_waitingLabel);
	mainLayout->addWidget(m_textLabel);
	mainLayout->addStretch();

	beginHLayout();
	addLayout(mainLayout, false);
	endHLayout();

	QPushButton *closeButton = new QPushButton(tr("Close"));
	connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));

	addButtonBarWidget(closeButton);

	// 0. Connect for svn errors (that may occurs)
	connect(&m_thread, SIGNAL(error(const QString &)), this, SLOT(onError(const QString &)));

	// 1. Getting status
	connect(&m_thread, SIGNAL(statusRetrieved(const QString &)), this, SLOT(onStatusRetrieved(const QString &)));
	m_thread.getSVNStatus(m_workingDir, m_files, true);
}

//-----------------------------------------------------------------------------

void SVNMultiFrameRangeLockInfoDialog::onError(const QString &errorString)
{
	m_waitingLabel->hide();
	m_textLabel->setText(errorString);
}

//-----------------------------------------------------------------------------

void SVNMultiFrameRangeLockInfoDialog::onStatusRetrieved(const QString &xmlResponse)
{
	m_waitingLabel->hide();

	SVNStatusReader sr(xmlResponse);
	QList<SVNStatus> status = sr.getStatus();

	// Fill_lockInfos list
	QList<SVNPartialLockInfo> lockInfos;
	SVNPartialLockInfo info;
	info.m_from = 0;
	int count = status.size();
	for (int i = 0; i < count; i++) {
		SVNStatus s = status.at(i);
		if (s.m_isLocked) {
			if (info.m_userName != s.m_lockOwner && info.m_userName != "") {
				lockInfos.append(info);
				info.m_from = 0;
			}
			info.m_userName = s.m_lockOwner;
			if (info.m_from == 0) {
				info.m_from = i + 1;
				info.m_to = i + 1;
			} else
				info.m_to = i + 1;
		}
	}

	if (info.m_userName != "" && info.m_from != 0)
		lockInfos.append(info);

	if (lockInfos.isEmpty())
		m_textLabel->setText(tr("No frame range edited."));
	else {
		QString temp;
		for (int i = 0; i < lockInfos.size(); i++) {
			if (i != 0)
				temp.append("\n\n");
			SVNPartialLockInfo lock = lockInfos.at(i);
			temp.append(tr("%1 is editing frames from %2 to %3").arg(lock.m_userName).arg(lock.m_from).arg(lock.m_to));
		}
		m_textLabel->setText(temp);
	}
}


text:
function dn = datelist(sdate, edate, months, days, hrs, mins, secs);
%DATELIST Lists datenumbers for months/days/hours/etc between two dates
%
% dn = datelist(sdate, edate, months, days, hrs, mins, secs);
%
% This lists all dates between the two given dates that match the criteria
% defined in the remaining input variables.  If any of the time variables
% are not included, they are set to the value in brackets.
%
% Input variables:
%
%   sdate:  starting date, as datenumber, date vector, or date string
%
%   edate:  ending date, as datenumber, date vector, or date string
%
%   months: months to include [1]
%
%   days:   days of the month to include [1]
%
%   hrs:    hours to include [0]
%
%   mins:   minutes to include [0]
%
%   secs:   seconds to include [0]
%
% Output variables:
%
%   dn:     vector of datenumbers
%
% Examples:
%
% dn = datelist(now, now-10, 1:12, 1:31, 0:23); % list all hours from the
%                                               % last 10 days
%
% dn = datelist('2000-01-01', '2005-01-01', 1:3:12); % 4 months/year for 5
%                                                    % years, 1st of the
%                                                    % month

% Copyright 2013 Kelly Kearney

isdv = @(x) isnumeric(x) && isvector(x) && length(x)==6;

if ~isdv(sdate)
    sdate = datevec(sdate);
end
if ~isdv(edate)
    edate = datevec(edate);
end

dv = [sdate; edate];

yr = (dv(1,1):dv(2,1))';

if nargin < 3
    months = 1;
end
if nargin < 4
    days = 1;
end
if nargin < 5
    hrs = 0;
end
if nargin < 6
    mins = 0;
end
if nargin < 7
    secs = 0;
end

[yr, months, days, hrs, mins, secs] = ndgrid(yr, months, days, hrs, mins, secs);
dvall = [yr(:), months(:), days(:), hrs(:), mins(:), secs(:)];
dn = datenum(dvall);

dn = unique(dn); % Duplicates arise from 31st, leap year, etc
dn(dn < datenum(sdate) | dn > datenum(edate)) = [];


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal" android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal">

        <Button
        android:id="@+id/prev"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/previous_button"
            android:textColor="#FFFFFF"
            android:background="#33B5E5"
            />

        <Button
            android:id="@+id/next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/next_button"
            android:textColor="#FFFFFF"
            android:background="#33B5E5"
            />

        <Button
            android:id="@+id/suspend"
            android:layout_marginLeft="@dimen/suspend_button_margin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/suspend_button"
            android:textColor="#FFFFFF"
            android:background="#1395C5"
            />

    </LinearLayout>

    <ImageView
        android:id="@+id/img1"
        android:src="@drawable/corner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        />
</LinearLayout>


text:
defineSuite([
        'Core/VideoSynchronizer',
        'Core/Clock',
        'Core/FeatureDetection',
        'Core/Iso8601',
        'Core/JulianDate',
        'Core/Math',
        'Specs/pollToPromise'
    ], function(
        VideoSynchronizer,
        Clock,
        FeatureDetection,
        Iso8601,
        JulianDate,
        CesiumMath,
        pollToPromise) {
    'use strict';

    //Video textures do not work on Internet Explorer
    if (FeatureDetection.isInternetExplorer()) {
        return;
    }

    function loadVideo() {
        var element = document.createElement('video');
        var source = document.createElement('source');
        source.setAttribute('src', 'http://cesiumjs.org/videos/Sandcastle/big-buck-bunny_trailer.webm');
        source.setAttribute('type', 'video/webm');
        element.appendChild(source);

        source = document.createElement('source');
        source.setAttribute('src', 'http://cesiumjs.org/videos/Sandcastle/big-buck-bunny_trailer.mp4');
        source.setAttribute('type', 'video/mp4');
        element.appendChild(source);

        source = document.createElement('source');
        source.setAttribute('src', 'http://cesiumjs.org/videos/Sandcastle/big-buck-bunny_trailer.mov');
        source.setAttribute('type', 'video/quicktime');
        element.appendChild(source);

        return element;
    }

    it('Can default construct', function() {
        var videoSynchronizer = new VideoSynchronizer();

        expect(videoSynchronizer.clock).not.toBeDefined();
        expect(videoSynchronizer.element).not.toBeDefined();
        expect(videoSynchronizer.epoch).toBe(Iso8601.MINIMUM_VALUE);
        expect(videoSynchronizer.tolerance).toBe(1.0);
        expect(videoSynchronizer.isDestroyed()).toBe(false);
        expect(videoSynchronizer.destroy()).not.toBeDefined();
        expect(videoSynchronizer.isDestroyed()).toBe(true);
    });

    it('Can construct with options', function() {
        var clock = new Clock();
        var element = document.createElement('video');
        var epoch = new JulianDate();
        var tolerance = 0.15;

        var videoSynchronizer = new VideoSynchronizer({
            clock : clock,
            element : element,
            epoch : epoch,
            tolerance: tolerance
        });

        expect(videoSynchronizer.clock).toBe(clock);
        expect(videoSynchronizer.element).toBe(element);
        expect(videoSynchronizer.epoch).toBe(epoch);
        expect(videoSynchronizer.tolerance).toBe(tolerance);
        expect(videoSynchronizer.isDestroyed()).toBe(false);
        expect(videoSynchronizer.destroy()).not.toBeDefined();
        expect(videoSynchronizer.isDestroyed()).toBe(true);
    });

    it('Syncs time when looping', function() {
        var epoch = JulianDate.fromIso8601('2015-11-01T00:00:00Z');
        var clock = new Clock();
        clock.shouldAnimate = false;
        clock.currentTime = epoch.clone();

        var element = loadVideo();
        element.loop = true;

        var videoSynchronizer = new VideoSynchronizer({
            clock : clock,
            element : element,
            epoch : epoch
        });

        return pollToPromise(function() {
            clock.tick();
            return element.currentTime === 0;
        }).then(function() {
            clock.currentTime = JulianDate.addSeconds(epoch, 10, clock.currentTime);
            return pollToPromise(function() {
                clock.tick();
                return element.currentTime === 10;
            });
        }).then(function() {
            clock.currentTime = JulianDate.addSeconds(epoch, 60, clock.currentTime);
            return pollToPromise(function() {
                clock.tick();
                return CesiumMath.equalsEpsilon(element.currentTime, 60 - element.duration, CesiumMath.EPSILON3);
            });
        }).then(function() {
            clock.currentTime = JulianDate.addSeconds(epoch, -1, clock.currentTime);
            return pollToPromise(function() {
                clock.tick();
                return CesiumMath.equalsEpsilon(element.currentTime, element.duration - 1, CesiumMath.EPSILON1);
            });
        }).then(function() {
            videoSynchronizer.destroy();
        });
    });

    it('Syncs time when not looping', function() {
        var epoch = JulianDate.fromIso8601('2015-11-01T00:00:00Z');
        var clock = new Clock();
        clock.shouldAnimate = false;
        clock.currentTime = epoch.clone();

        var element = loadVideo();

        var videoSynchronizer = new VideoSynchronizer({
            clock : clock,
            element : element,
            epoch : epoch
        });

        return pollToPromise(function() {
            clock.tick();
            return element.currentTime === 0;
        }).then(function() {
            clock.currentTime = JulianDate.addSeconds(epoch, 10, clock.currentTime);
            return pollToPromise(function() {
                clock.tick();
                return element.currentTime === 10;
            });
        }).then(function() {
            clock.currentTime = JulianDate.addSeconds(epoch, 60, clock.currentTime);
            return pollToPromise(function() {
                clock.tick();
                return CesiumMath.equalsEpsilon(element.currentTime, element.duration, CesiumMath.EPSILON3);
            });
        }).then(function() {
            clock.currentTime = JulianDate.addSeconds(epoch, -1, clock.currentTime);
            return pollToPromise(function() {
                clock.tick();
                return element.currentTime === 0;
            });
        }).then(function() {
            videoSynchronizer.destroy();
        });
    });

    it('Plays/pauses video based on clock', function() {
        var epoch = JulianDate.fromIso8601('2015-11-01T00:00:00Z');
        var clock = new Clock();

        // Since Chrome doesn't allow video playback without user
        // interaction, we use a mock element.
        var element = jasmine.createSpyObj('MockVideoElement', ['addEventListener', 'removeEventListener', 'play', 'pause']);
        element.paused = false;
        element.play.and.callFake(function() {
            this.paused = false;
        });
        element.pause.and.callFake(function() {
            this.paused = true;
        });

        var videoSynchronizer = new VideoSynchronizer({
            clock : clock,
            element : element,
            epoch : epoch
        });

        clock.shouldAnimate = false;
        clock.tick();
        expect(element.pause.calls.count()).toEqual(1);

        clock.shouldAnimate = true;
        clock.tick();
        expect(element.play.calls.count()).toEqual(1);

        clock.shouldAnimate = false;
        clock.tick();
        expect(element.pause.calls.count()).toEqual(2);

        videoSynchronizer.destroy();
    });
});


text:
package com.halcyon.common;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;

import com.halcyon.common.lh.MultiItemRAdapter;
import com.halcyon.common.lh.MultiItemRTypeSupport;
import com.halcyon.common.lh.RHolder;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private RecyclerView mRecyclerView;
    private static final int TYPE_NORMAL = 0;
    private static final int TYPE_SPECIAL = 1;
    private List<String> mDatas;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDatas = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            mDatas.add("数据"+i);
        }

        mRecyclerView = (RecyclerView) this.findViewById(R.id.recyclerview);
        MultiItemRTypeSupport<String> support = new MultiItemRTypeSupport<String>() {
            @Override
            public int getLayoutId(int type) {
                if(type == TYPE_NORMAL){
                    return R.layout.item_listview;
                }
                return R.layout.item_listview_other;
            }

            @Override
            public int getItemViewType(int position, String s) {
                if(position % 5 == 0){
                    return TYPE_SPECIAL;
                }
                return TYPE_NORMAL;
            }
        };
        MultiItemRAdapter<String> adapter = new MultiItemRAdapter<String>(mDatas,support) {
            @Override
            public void convert(RHolder holder, String item, int position) {
                switch (getItemViewType(position)){
                    case TYPE_NORMAL:
                        holder.setText(R.id.tv_content,item);
                        break;
                    case TYPE_SPECIAL:
                        holder.setText(R.id.tv_content,"标题");
                        holder.itemView.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                startActivity(new Intent(getApplication(),ViceActivity.class));
                            }
                        });
                }

            }
        };

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setAdapter(adapter);
    }

}