/* * SSSync, a Simple and Stupid Synchronizer for data with multi-valued attributes * Copyright (C) 2014 Ludovic Pouzenc * * This file is part of SSSync. * * SSSync is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SSSync is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with SSSync. If not, see */ package data.filters; import java.util.Iterator; import java.util.NoSuchElementException; import data.MVDataEntry; import data.io.AbstractMVDataReader; import data.io.MVDataReader; /** * Combines arbitrary number of MVData* sources while behaving same as AbstractMVDataReader. * This could enable a sync implementation to merge multiple sources * before sync'ing in a transparent manner. * To prevent memory consumption, this assumes that all sources will be read * with lexicographical ascending order on the "key" field. * * @author lpouzenc */ public class MVDataCombiner extends AbstractMVDataReader { public enum MVDataCombineMode { PRIMARY_SOURCE, MERGE_APPEND, MERGE_REPLACE, OVERRIDE }; private final MVDataReader[] readers; private final MVDataCombineMode[] mergeModes; private transient Iterator[] readerIterators; private transient MVDataEntry[] lookAheadData; private transient String lastKey; public MVDataCombiner(String dataSourceName, MVDataReader[] readers, MVDataCombineMode mergeModes[]) { if ( readers == null || mergeModes == null || (mergeModes.length != readers.length) ) { throw new IllegalArgumentException("readers and mergeModes arrays should have same size"); } if ( ! (mergeModes.length > 0) || mergeModes[0] != MVDataCombineMode.PRIMARY_SOURCE ) { throw new IllegalArgumentException("MVDataCombiner first mergeModes should always be PRIMARY_SOURCE"); } this.dataSourceName = dataSourceName; this.readers = readers.clone(); this.mergeModes = mergeModes.clone(); } /** * {@inheritDoc} */ @Override @SuppressWarnings("unchecked") /* for new Iterator[...] */ public Iterator iterator() { // Be cautious to reset everything readerIterators = new Iterator[readers.length]; for (int i=0; i 0 ) { minKey = minKeyCandidate; } } } // Sanity checks if ( minKey == null ) { // Every reader is empty and look-ahead buffer is empty (hasNext() should have said false) throw new NoSuchElementException(); } return minKey; } // Boring accessors public String getLastKey() { return lastKey; } }