All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.interedition.text.simple.SimpleTextRepository Maven / Gradle / Ivy

The newest version!
package eu.interedition.text.simple;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.io.CharStreams;
import eu.interedition.text.Anchor;
import eu.interedition.text.Layer;
import eu.interedition.text.Name;
import eu.interedition.text.Query;
import eu.interedition.text.QueryResult;
import eu.interedition.text.Text;
import eu.interedition.text.TextRange;
import eu.interedition.text.TextRepository;
import eu.interedition.text.util.BatchLayerAdditionSupport;
import eu.interedition.text.util.UpdateSupport;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * @author Gregor Middell
 */
public class SimpleTextRepository implements TextRepository, UpdateSupport, BatchLayerAdditionSupport {

    private Map> contents = Maps.newHashMap();
    private SetMultimap> targets = HashMultimap.create();

    @Override
    public Layer findByIdentifier(long id) {
        return contents.get(id);
    }

    @Override
    public Iterable> add(Iterable> batch) throws IOException {
        final List> added = Lists.newLinkedList();
        for (Layer layer : batch) {
            added.add(add(layer.getName(), new StringReader(layer.read()), layer.data(), layer.getAnchors()));
        }
        return added;
    }

    public Layer add(Name name, Reader text, T data, Set> anchors) throws IOException {
        final SimpleLayer added = new SimpleLayer(name, CharStreams.toString(text), data, anchors, this);
        for (Anchor anchor : anchors) {
            this.targets.put(anchor.getText(), added);
        }
        contents.put(added.getId(), added);
        return added;
    }

    public Layer add(Name name, Reader text, T data, Anchor anchor) throws IOException {
        return add(name, text, data, Collections.singleton(anchor));
    }

    @Override
    public QueryResult query(Query query) {
        return new SimpleQueryResult(Iterables.filter(contents.values(), TO_PREDICATE.apply(query.getRoot())));
    }

    @SuppressWarnings("unchecked")
    @Override
    public void delete(Iterable> layers) {
        for (SimpleLayer layer : Lists.newLinkedList(Iterables.filter(layers, SimpleLayer.class))) {
            if (contents.remove(layer.getId()) != null) {
                for (Layer dependent : targets.removeAll(layer)) {
                    delete(Collections.singleton(dependent));
                }
            }
        }
    }

    static class SimpleQueryResult implements QueryResult {
        final Iterable> result;

        SimpleQueryResult(Iterable> result) {
            this.result = result;
        }

        @Override
        public Iterator> iterator() {
            return result.iterator();
        }

        @Override
        public void close() {
        }
    }

    private final Function>> TO_PREDICATE = new Function>>() {
        @SuppressWarnings("unchecked")
        @Override
        public Predicate> apply(@Nullable final Query input) {
            if (input instanceof Query.Any) {
                return Predicates.alwaysTrue();
            } else if (input instanceof Query.None) {
                return Predicates.alwaysFalse();
            } else if (input instanceof Query.OperatorQuery.And) {
                return Predicates.and(Iterables.transform(((Query.OperatorQuery) input).getOperands(), this));
            } else if (input instanceof Query.OperatorQuery.Or) {
                return Predicates.or(Iterables.transform(((Query.OperatorQuery) input).getOperands(), this));
            } else if (input instanceof Query.RangeQuery.RangeEnclosesQuery) {
                return new AnyAnchorPredicate(new RangeEnclosesPredicate(((Query.RangeQuery.RangeEnclosesQuery) input).getRange()));
            } else if (input instanceof Query.RangeQuery.RangeLengthQuery) {
                return new AnyAnchorPredicate(new RangeLengthPredicate(((Query.RangeQuery.RangeLengthQuery) input).getRange().length()));
            } else if (input instanceof Query.RangeQuery.RangeOverlapQuery) {
                return new AnyAnchorPredicate(new RangeOverlapPredicate(((Query.RangeQuery.RangeOverlapQuery) input).getRange()));
            } else if (input instanceof Query.LocalNameQuery) {
                return new LocalNamePredicate(((Query.LocalNameQuery) input).getLn());
            } else if (input instanceof Query.NameQuery) {
                return new NamePredicate(((Query.NameQuery) input).getName());
            } else if (input instanceof Query.LayerIdentityQuery) {
                return new LayerIdentityPredicate(((Query.LayerIdentityQuery) input).getId());
            } else if (input instanceof Query.TextQuery) {
                return new AnyAnchorPredicate(new TextPredicate(((Query.TextQuery) input).getText()));
            }
            throw new IllegalArgumentException(input.toString());
        }
    };

    public void updateText(Layer target, Reader text) throws IOException {
        ((SimpleLayer) target).text = CharStreams.toString(text);
    }

    public static class LayerIdentityPredicate implements Predicate> {

        private final long id;

        public LayerIdentityPredicate(long id) {
            this.id = id;
        }

        @Override
        public boolean apply(@Nullable Layer input) {
            return (id == input.getId());
        }
    }

    public static class AnyAnchorPredicate implements Predicate> {

        private Predicate> anchorPredicate;

        public AnyAnchorPredicate(Predicate> anchorPredicate) {
            this.anchorPredicate = anchorPredicate;
        }

        @Override
        public boolean apply(@Nullable Layer input) {
            return Iterables.any(input.getAnchors(), anchorPredicate);
        }
    }

    public static class LocalNamePredicate implements Predicate> {

        private final String ln;

        public LocalNamePredicate(String ln) {
            this.ln = ln;
        }

        @Override
        public boolean apply(@Nullable Layer input) {
            return ln.equals(input.getName().getLocalName());
        }
    }

    public static class NamePredicate implements Predicate> {

        private final Name name;

        public NamePredicate(Name name) {
            this.name = name;
        }

        @Override
        public boolean apply(@Nullable Layer input) {
            return input.getName().equals(name);
        }
    }


    public static class TextPredicate implements Predicate> {

        private final Layer target;

        public TextPredicate(Layer target) {
            this.target = target;
        }

        @Override
        public boolean apply(@Nullable Anchor input) {
            return input.getText().equals(target);
        }
    }

    public static class RangeEnclosesPredicate implements Predicate> {

        private final TextRange range;

        public RangeEnclosesPredicate(TextRange range) {
            this.range = range;
        }

        @Override
        public boolean apply(@Nullable Anchor input) {
            return range.encloses(input.getRange());
        }
    }

    public static class RangeLengthPredicate implements Predicate> {

        private final long length;

        public RangeLengthPredicate(long length) {
            this.length = length;
        }

        @Override
        public boolean apply(@Nullable Anchor input) {
            return (input.getRange().length() == length);
        }
    }

    public static class RangeOverlapPredicate implements Predicate> {

        private final TextRange range;

        public RangeOverlapPredicate(TextRange range) {
            this.range = range;
        }

        @Override
        public boolean apply(@Nullable Anchor input) {
            return range.hasOverlapWith(input.getRange());
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy