
org.metafacture.triples.AbstractTripleSort Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of metafacture-triples Show documentation
Show all versions of metafacture-triples Show documentation
Modules for working with triples
/*
* 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