Package org.lilyproject.indexer.model.indexerconf

Source Code of org.lilyproject.indexer.model.indexerconf.DefaultFormatter$ListFormatter

/*
* Copyright 2010 Outerthought bvba
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lilyproject.indexer.model.indexerconf;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.lilyproject.repository.api.HierarchyPath;
import org.lilyproject.repository.api.LRepository;
import org.lilyproject.repository.api.QName;
import org.lilyproject.repository.api.Record;
import org.lilyproject.repository.api.RepositoryException;
import org.lilyproject.repository.api.TypeManager;
import org.lilyproject.repository.api.ValueType;

/**
* A default implementation of a formatter than is able to treat any value.
*/
public class DefaultFormatter implements Formatter {

    private static final Map<String, ValueFormatter> FORMATTERS;
    static {
        FORMATTERS = new HashMap<String, ValueFormatter>();
        FORMATTERS.put("LIST", new ListFormatter());
        FORMATTERS.put("PATH", new PathFormatter());
        FORMATTERS.put("RECORD", new RecordFormatter());
        FORMATTERS.put("DATE", new DateFormatter());
        FORMATTERS.put("DATETIME", new DateTimeFormatter());
    }
    private static final ValueFormatter ALL_FORMATTER = new AllFormatter();

    @Override
    public List<String> format(List<IndexValue> indexValues, LRepository repository)
            throws InterruptedException {

        List<String> results = new ArrayList<String>();

        for (IndexValue value : filterValues(indexValues)) {
            FormatContext formatCtx = new FormatContext(repository);

            ValueType valueType = value.fieldType.getValueType();
            if (valueType.getBaseName().equals("LIST")) {
                // The values of the first list-level are supplied as individual IndexValues
                valueType = valueType.getNestedValueType();
            }

            String result = formatCtx.format(value.value, valueType, formatCtx);

            if (result != null) {
                results.add(result);
            } else {
                results.addAll(formatCtx.results);
            }
        }

        return results;
    }

    protected List<IndexValue> filterValues(List<IndexValue> indexValues) {
        return indexValues;
    }

    protected ValueFormatter getFormatter(ValueType valueType) {
        ValueFormatter formatter = FORMATTERS.get(valueType.getBaseName());
        return formatter == null ? ALL_FORMATTER : formatter;
    }

    public class FormatContext implements ValueFormatter {
        /**
         * This stack can be useful for formatters that want to behave differently depending on
         * how they are nested in other types. For example in case of nested lists, you might
         * want to format each nesting level differently.
         */
        Deque<ValueType> valueTypeStack = new ArrayDeque<ValueType>();
        LRepository repository;
        List<String> results = new ArrayList<String>();

        public FormatContext(LRepository repository) {
            this.repository = repository;
        }

        @Override
        public String format(Object value, ValueType valueType, FormatContext formatCtx) throws InterruptedException {
            valueTypeStack.push(valueType);

            String result = getFormatter(valueType).format(value, valueType, this);

            valueTypeStack.pop();

            return result;
        }
    }

    public static interface ValueFormatter {
        /**
         * This method has the choice of either returning a formatted value, or appending it to the supplied
         * results list. Appending it to the results list has the effect of sending a multi-value to the indexer
         * (so the index field needs to support multiple values), while returning a string will cause the value
         * to be used by the parent formatter.
         */
        public String format(Object value, ValueType valueType, FormatContext formatCtx) throws InterruptedException;
    }


    public static void appendNonNull(StringBuilder builder, String text) {
        if (text != null) {
            builder.append(text);
        }
    }

    public static String returnBuilderResult(StringBuilder builder) {
        return builder.length() > 0 ? builder.toString() : null;
    }

    protected static class ListFormatter implements ValueFormatter {
        @Override
        public String format(Object list, ValueType valueType, FormatContext formatCtx) throws InterruptedException {
            StringBuilder builder = new StringBuilder();

            for (Object value : (List)list) {
                String formatted = formatCtx.format(value, valueType.getNestedValueType(), formatCtx);

                // separate the values by a space
                if (builder.length() > 0) {
                    builder.append(" ");
                }
                builder.append(formatted);
            }

            return returnBuilderResult(builder);
        }
    }

    protected static class PathFormatter implements ValueFormatter {
        @Override
        public String format(Object path, ValueType valueType, FormatContext formatCtx) throws InterruptedException {
            StringBuilder builder = new StringBuilder();

            for (Object value : (HierarchyPath)path) {
                String formatted = formatCtx.format(value, valueType.getNestedValueType(), formatCtx);
                builder.append("/");
                builder.append(formatted);
            }

            return returnBuilderResult(builder);
        }
    }

    protected static class RecordFormatter implements ValueFormatter {
        @Override
        public String format(Object record, ValueType valueType, FormatContext formatCtx) throws InterruptedException {
            StringBuilder builder = new StringBuilder();
            TypeManager typeManager = formatCtx.repository.getTypeManager();

            for (Map.Entry<QName, Object> field : ((Record)record).getFields().entrySet()) {
                ValueType fieldValueType;
                try {
                    fieldValueType = typeManager.getFieldTypeByName(field.getKey()).getValueType();
                } catch (RepositoryException e) {
                    // error loading field type: skip this field
                    continue;
                }

                String result = formatCtx.format(field.getValue(), fieldValueType, formatCtx);
                if (result != null) {
                    if (builder.length() > 0) {
                        builder.append(" ");
                    }
                    builder.append(result);
                }
            }

            return returnBuilderResult(builder);
        }
    }

    protected static class DateFormatter implements ValueFormatter {
        @Override
        public String format(Object value, ValueType valueType, FormatContext formatCtx) throws InterruptedException {
            LocalDate date = (LocalDate)value;
            return date.toDateTimeAtStartOfDay(DateTimeZone.UTC).toString() + "/DAY";
        }
    }

    protected static class DateTimeFormatter implements ValueFormatter {
        @Override
        public String format(Object value, ValueType valueType, FormatContext formatCtx) throws InterruptedException {
            DateTime dateTime = (DateTime)value;
            return dateTime.toDateTime(DateTimeZone.UTC).toString();
        }
    }

    protected static class AllFormatter implements ValueFormatter {
        @Override
        public String format(Object value, ValueType valueType, FormatContext formatCtx) throws InterruptedException {
            return value.toString();
        }
    }

}
TOP

Related Classes of org.lilyproject.indexer.model.indexerconf.DefaultFormatter$ListFormatter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.