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

net.maizegenetics.util.GeneralAnnotationStorage Maven / Gradle / Ivy

/*
 *  GeneralAnnotationStorage
 * 
 *  Created on Feb. 2, 2015
 */
package net.maizegenetics.util;

import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Ordering;
import com.google.common.collect.SetMultimap;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author Ed Buckler
 * @author Terry Casstevens
 */
public class GeneralAnnotationStorage implements GeneralAnnotation {

    public static final GeneralAnnotationStorage EMPTY_ANNOTATION_STORAGE = new GeneralAnnotationStorage();

    private static final double[] EMPTY_DOUBLE_ARRAY = new double[0];

    private static final int MAX_CACHE_SIZE = 1_000_000;

    private static final Map, Map.Entry> CACHE = Collections.synchronizedMap(new LinkedHashMap, Map.Entry>((3 * MAX_CACHE_SIZE) / 2) {

        @Override
        protected boolean removeEldestEntry(Map.Entry, Map.Entry> eldest) {
            return size() > MAX_CACHE_SIZE;
        }

    });

    private static Map.Entry getCanonicalAnnotation(String key, String value) {
        Map.Entry temp = new AbstractMap.SimpleImmutableEntry<>(key, value);
        Map.Entry entry = CACHE.putIfAbsent(temp, temp);
        return (entry == null) ? temp : entry;
    }

    private final Map.Entry[] myAnnotations;

    private GeneralAnnotationStorage(Builder builder) {
        myAnnotations = (Map.Entry[]) new Map.Entry[builder.myAnnotations.size()];
        for (int i = 0; i < builder.myAnnotations.size(); i++) {
            myAnnotations[i] = builder.myAnnotations.get(i);
        }
    }

    private GeneralAnnotationStorage() {
        myAnnotations = (Map.Entry[]) new Map.Entry[0];
    }

    public static Builder getBuilder() {
        return new Builder();
    }

    @Override
    public String[] getTextAnnotation(String annoName) {
        List result = new ArrayList<>(1);
        for (Map.Entry me : myAnnotations) {
            if (me.getKey().equals(annoName)) {
                result.add(me.getValue());
            }
        }
        return result.toArray(new String[result.size()]);
    }

    @Override
    public Map getConcatenatedTextAnnotations() {
        Map result = new HashMap<>();
        for (Map.Entry me : myAnnotations) {
            String value = result.get(me.getKey());
            if (value == null) {
                result.put(me.getKey(), me.getValue());
            } else {
                result.put(me.getKey(), value + "," + me.getValue());
            }
        }
        return result;
    }

    @Override
    public double[] getQuantAnnotation(String annoName) {
        try {
            ArrayList result = new ArrayList<>(1);
            for (Map.Entry me : myAnnotations) {
                if (me.getKey().equals(annoName)) {
                    result.add(Double.parseDouble(me.getValue()));
                }
            }
            if (result.isEmpty()) {
                return EMPTY_DOUBLE_ARRAY;
            }
            double[] d = new double[result.size()];
            for (int i = 0; i < result.size(); i++) {
                d[i] = result.get(i);
            }
            return d;
        } catch (Exception e) {
            return EMPTY_DOUBLE_ARRAY;
        }
    }

    @Override
    public double getAverageAnnotation(String annoName) {
        double[] values = getQuantAnnotation(annoName);
        if (values.length == 0) {
            return Double.NaN;
        } else if (values.length == 1) {
            return values[0];
        } else {
            double result = 0.0;
            for (double current : values) {
                result += current;
            }
            return result / (double) values.length;
        }
    }

    @Override
    public boolean isAnnotatedWithValue(String annoName, String annoValue) {
        for (Map.Entry me : myAnnotations) {
            if (me.getKey().equals(annoName) && me.getValue().equals(annoValue)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Map.Entry[] getAllAnnotationEntries() {
        return Arrays.copyOf(myAnnotations, myAnnotations.length);
    }

    @Override
    public Set getAnnotationKeys() {
        Set result = new HashSet<>();
        for (Map.Entry me : myAnnotations) {
            result.add(me.getKey());
        }
        return result;
    }

    @Override
    public SetMultimap getAnnotationAsMap() {
        ImmutableSetMultimap.Builder result = new ImmutableSetMultimap.Builder()
                .orderKeysBy(Ordering.natural()).orderValuesBy(Ordering.natural());
        for (Map.Entry en : myAnnotations) {
            result.put(en.getKey(), en.getValue());
        }
        return result.build();
    }

    @Override
    public int numAnnotations() {
        return myAnnotations.length;
    }

    public static class Builder {

        private final List> myAnnotations = new ArrayList<>(0);

        private Builder() {
        }

        public Builder addAnnotation(String key, String value) {
            myAnnotations.add(getCanonicalAnnotation(key, value));
            return this;
        }

        public Builder addAnnotation(String key, Number value) {
            myAnnotations.add(getCanonicalAnnotation(key, value.toString()));
            return this;
        }

        public Builder addAnnotations(GeneralAnnotation existing) {
            if (existing == null) {
                return this;
            }
            myAnnotations.addAll(Arrays.asList(existing.getAllAnnotationEntries()));
            return this;
        }

        public GeneralAnnotationStorage build() {
            if (myAnnotations.isEmpty()) {
                return EMPTY_ANNOTATION_STORAGE;
            }
            Collections.sort(myAnnotations, (Map.Entry s1, Map.Entry s2) -> {
                int keyComp = s1.getKey().compareTo(s2.getKey());
                if (keyComp != 0) {
                    return keyComp;
                }
                return s1.getValue().compareTo(s2.getValue());
            });
            return new GeneralAnnotationStorage(this);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy