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

org.metafacture.triples.AbstractTripleSort Maven / Gradle / Ivy

There is a newer version: 6.2.0
Show newest version
/*
 * Copyright 2013, 2014 Deutsche Nationalbibliothek
 *
 * 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.metafacture.triples;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

import org.metafacture.framework.MetafactureException;
import org.metafacture.framework.ObjectReceiver;
import org.metafacture.framework.helpers.DefaultObjectPipe;
import org.metafacture.framework.objects.Triple;

/**
 * @author markus geipel
 *
 */
public abstract class AbstractTripleSort extends DefaultObjectPipe> implements MemoryWarningSystem.Listener {
    /**
     * specifies the comparator
     */
    public enum Compare {
        SUBJECT, PREDICATE, OBJECT, ALL;
    }

    /**
     * sort order
     *
     */
    public enum Order {
        INCREASING {
            @Override
            public int order(final int indicator) {
                return indicator;
            }
        },
        DECREASING {
            @Override
            public int order(final int indicator) {
                return -indicator;
            }
        };
        public abstract int order(int indicator);
    }

    private final List buffer = new ArrayList();
    private final List tempFiles;
    private Compare compare = Compare.SUBJECT;
    private Order order = Order.INCREASING;
    private volatile boolean memoryLow;

    public AbstractTripleSort() {
        MemoryWarningSystem.addListener(this);
        tempFiles = new ArrayList(); // Initialized here to let the
                                            // compiler enforce the call to
                                            // super() in subclasses.
    }

    @Override
    public final void memoryLow(final long usedMemory, final long maxMemory) {
        memoryLow = true;
    }

    protected final void setCompare(final Compare compare) {
        this.compare = compare;
    }

    protected final Compare getCompare() {
        return compare;
    }

    protected final void setSortOrder(final Order order) {
        this.order = order;
    }

    @Override
    public final void process(final Triple namedValue) {
        if (memoryLow) {
            try {
                if (!buffer.isEmpty()) {
                    nextBatch();
                }
            } catch (final IOException e) {
                throw new MetafactureException("Error writing to temp file after sorting", e);
            } finally {
                memoryLow = false;
            }
        }
        buffer.add(namedValue);
    }

    private void nextBatch() throws IOException {
        Collections.sort(buffer, createComparator(compare, order));
        final File tempFile = File.createTempFile("sort", "namedValues", null);
        tempFile.deleteOnExit();
        final ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(tempFile));

        try {
            for (final Triple triple : buffer) {
                triple.write(out);
            }
        } finally {
            out.close();
        }
        buffer.clear();
        tempFiles.add(tempFile);
    }

    @Override
    public final void onCloseStream() {

        if (tempFiles.isEmpty()) {
            Collections.sort(buffer, createComparator(compare, order));
            for (final Triple triple : buffer) {
                sortedTriple(triple);
            }
            onFinished();
        } else {
            final Comparator comparator = createComparator(compare, order);
            final PriorityQueue queue = new PriorityQueue(11,
                    new Comparator() {
                        // private final Comparator comparator =
                        // getComparator();

                        @Override
                        public int compare(final SortedTripleFileFacade o1, final SortedTripleFileFacade o2) {
                            return comparator.compare(o1.peek(), o2.peek());
                        }
                    });
            try {
                nextBatch();
                for (final File file : tempFiles) {
                    queue.add(new SortedTripleFileFacade(file));
                }

                while (queue.size() > 0) {
                    final SortedTripleFileFacade sortedFileFacade = queue.poll();
                    final Triple triple = sortedFileFacade.pop();
                    sortedTriple(triple);
                    if (sortedFileFacade.isEmpty()) {
                        sortedFileFacade.close();
                    } else {
                        queue.add(sortedFileFacade);
                    }
                }
                onFinished();
            } catch (final IOException e) {
                throw new MetafactureException("Error merging temp files", e);
            } finally {
                for (final SortedTripleFileFacade sortedFileFacade : queue) {
                    sortedFileFacade.close();
                }
            }
        }
        MemoryWarningSystem.removeListener(this);
    }

    protected void onFinished() {
        // nothing to do

    }

    protected abstract void sortedTriple(Triple namedValue);

    public final Comparator createComparator() {
        return createComparator(compare, order);
    }

    public static Comparator createComparator(final Compare compareBy, final Order order) {
        final Comparator comparator;
        switch (compareBy) {
        case ALL:
            comparator = new Comparator() {
                @Override
                public int compare(final Triple o1, final Triple o2) {
                    return order.order(o1.compareTo(o2));
                }
            };
            break;
        case OBJECT:
            comparator = new Comparator() {
                @Override
                public int compare(final Triple o1, final Triple o2) {
                    return order.order(o1.getObject().compareTo(o2.getObject()));
                }
            };
            break;
        case SUBJECT:
            comparator = new Comparator() {
                @Override
                public int compare(final Triple o1, final Triple o2) {
                    return order.order(o1.getSubject().compareTo(o2.getSubject()));
                }
            };
            break;
        case PREDICATE:
        default:
            comparator = new Comparator() {
                @Override
                public int compare(final Triple o1, final Triple o2) {
                    return order.order(o1.getPredicate().compareTo(o2.getPredicate()));
                }
            };
            break;
        }

        return comparator;
    }

    @Override
    public final void onResetStream() {
        buffer.clear();
        for (final File file : tempFiles) {
            if (file.exists()) {
                file.delete();
            }
        }
        tempFiles.clear();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy