chris@3: /*
chris@3: * SONEWS News Server
chris@3: * see AUTHORS for the list of contributors
chris@3: *
chris@3: * This program is free software: you can redistribute it and/or modify
chris@3: * it under the terms of the GNU General Public License as published by
chris@3: * the Free Software Foundation, either version 3 of the License, or
chris@3: * (at your option) any later version.
chris@3: *
chris@3: * This program is distributed in the hope that it will be useful,
chris@3: * but WITHOUT ANY WARRANTY; without even the implied warranty of
chris@3: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
chris@3: * GNU General Public License for more details.
chris@3: *
chris@3: * You should have received a copy of the GNU General Public License
chris@3: * along with this program. If not, see .
chris@3: */
chris@3:
chris@3: package org.sonews.storage;
chris@3:
chris@3: import java.util.ArrayList;
chris@3: import java.util.Collections;
chris@3: import java.util.List;
chris@3: import org.sonews.util.Pair;
chris@3:
chris@3: /**
chris@3: * An aggregated group is a group consisting of several "real" group.
chris@3: * @author Christian Lins
chris@3: * @since sonews/1.0
chris@3: */
chris@3: class AggregatedGroup extends Channel
chris@3: {
chris@3:
chris@3: static class GroupElement
chris@3: {
chris@3: private Group group;
chris@3: private long offsetStart, offsetEnd;
chris@3:
chris@3: public GroupElement(Group group, long offsetStart, long offsetEnd)
chris@3: {
chris@3: this.group = group;
chris@3: this.offsetEnd = offsetEnd;
chris@3: this.offsetStart = offsetStart;
chris@3: }
chris@3: }
chris@3:
chris@3: public static List getAll()
chris@3: {
chris@3: List all = new ArrayList();
chris@3: all.add(getByName("agg.test"));
chris@3: return all;
chris@3: }
chris@3:
chris@3: public static AggregatedGroup getByName(String name)
chris@3: {
chris@3: if("agg.test".equals(name))
chris@3: {
chris@3: AggregatedGroup agroup = new AggregatedGroup(name);
chris@3: agroup.addGroup(Group.getByName("agg.test0"), 0, 1000);
chris@3: agroup.addGroup(Group.getByName("agg.test1"), 2000, 4000);
chris@3: return agroup;
chris@3: }
chris@3: else
chris@3: return null;
chris@3: }
chris@3:
chris@3: private GroupElement[] groups = new GroupElement[2];
chris@3: private String name;
chris@3:
chris@3: public AggregatedGroup(String name)
chris@3: {
chris@3: this.name = name;
chris@3: }
chris@3:
chris@3: private long aggIdxToIdx(long aggIdx)
chris@3: throws StorageBackendException
chris@3: {
chris@3: assert groups != null && groups.length == 2;
chris@3: assert groups[0] != null;
chris@3: assert groups[1] != null;
chris@3:
chris@3: // Search in indices of group one
chris@3: List idxs0 = groups[0].group.getArticleNumbers();
chris@3: Collections.sort(idxs0);
chris@3: for(long idx : idxs0)
chris@3: {
chris@3: if(idx == aggIdx)
chris@3: {
chris@3: return idx;
chris@3: }
chris@3: }
chris@3:
chris@3: // Given aggIdx must be an index of group two
chris@3: List idxs1 = groups[1].group.getArticleNumbers();
chris@3: return 0;
chris@3: }
chris@3:
chris@3: private long idxToAggIdx(long idx)
chris@3: {
chris@3: return 0;
chris@3: }
chris@3:
chris@3: /**
chris@3: * Adds the given group to this aggregated set.
chris@3: * @param group
chris@3: * @param offsetStart Lower limit for the article ids range
chris@3: */
chris@3: public void addGroup(Group group, long offsetStart, long offsetEnd)
chris@3: {
chris@3: this.groups[groups[0] == null ? 0 : 1]
chris@3: = new GroupElement(group, offsetStart, offsetEnd);
chris@3: }
chris@3:
chris@3: @Override
chris@3: public Article getArticle(long idx)
chris@3: throws StorageBackendException
chris@3: {
chris@3: Article article = null;
chris@3:
chris@3: for(GroupElement groupEl : groups)
chris@3: {
chris@3: if(groupEl.offsetStart <= idx && groupEl.offsetEnd >= idx)
chris@3: {
chris@3: article = groupEl.group.getArticle(idx - groupEl.offsetStart);
chris@3: break;
chris@3: }
chris@3: }
chris@3:
chris@3: return article;
chris@3: }
chris@3:
chris@3: @Override
chris@3: public List> getArticleHeads(
chris@3: final long first, final long last)
chris@3: throws StorageBackendException
chris@3: {
chris@3: List> heads = new ArrayList>();
chris@3:
chris@3: for(GroupElement groupEl : groups)
chris@3: {
chris@3: List> partHeads = new ArrayList>();
chris@3: if(groupEl.offsetStart <= first && groupEl.offsetEnd >= first)
chris@3: {
chris@3: long end = Math.min(groupEl.offsetEnd, last);
chris@3: partHeads = groupEl.group.getArticleHeads
chris@3: (first - groupEl.offsetStart, end - groupEl.offsetStart);
chris@3: }
chris@3: else if(groupEl.offsetStart <= last && groupEl.offsetEnd >= last)
chris@3: {
chris@3: long start = Math.max(groupEl.offsetStart, first);
chris@3: partHeads = groupEl.group.getArticleHeads
chris@3: (start - groupEl.offsetStart, last - groupEl.offsetStart);
chris@3: }
chris@3:
chris@3: for(Pair partHead : partHeads)
chris@3: {
chris@3: heads.add(new Pair(
chris@3: partHead.getA() + groupEl.offsetStart, partHead.getB()));
chris@3: }
chris@3: }
chris@3:
chris@3: return heads;
chris@3: }
chris@3:
chris@3: @Override
chris@3: public List getArticleNumbers()
chris@3: throws StorageBackendException
chris@3: {
chris@3: List articleNumbers = new ArrayList();
chris@3:
chris@3: for(GroupElement groupEl : groups)
chris@3: {
chris@3: List partNums = groupEl.group.getArticleNumbers();
chris@3: for(Long partNum : partNums)
chris@3: {
chris@3: articleNumbers.add(partNum + groupEl.offsetStart);
chris@3: }
chris@3: }
chris@3:
chris@3: return articleNumbers;
chris@3: }
chris@3:
chris@3: @Override
chris@3: public long getIndexOf(Article art)
chris@3: throws StorageBackendException
chris@3: {
chris@3: for(GroupElement groupEl : groups)
chris@3: {
chris@3: long idx = groupEl.group.getIndexOf(art);
chris@3: if(idx > 0)
chris@3: {
chris@3: return idx;
chris@3: }
chris@3: }
chris@3: return -1;
chris@3: }
chris@3:
chris@3: public long getInternalID()
chris@3: {
chris@3: return -1;
chris@3: }
chris@3:
chris@3: @Override
chris@3: public String getName()
chris@3: {
chris@3: return this.name;
chris@3: }
chris@3:
chris@3: @Override
chris@3: public long getFirstArticleNumber()
chris@3: throws StorageBackendException
chris@3: {
chris@3: long first = Long.MAX_VALUE;
chris@3:
chris@3: for(GroupElement groupEl : groups)
chris@3: {
chris@3: first = Math.min(first, groupEl.group.getFirstArticleNumber() + groupEl.offsetStart);
chris@3: }
chris@3:
chris@3: return first;
chris@3: }
chris@3:
chris@3: @Override
chris@3: public long getLastArticleNumber()
chris@3: throws StorageBackendException
chris@3: {
chris@3: long last = 1;
chris@3:
chris@3: for(GroupElement groupEl : groups)
chris@3: {
chris@3: last = Math.max(last, groupEl.group.getLastArticleNumber() + groupEl.offsetStart);
chris@3: }
chris@3:
chris@3: return last + getPostingsCount(); // This is a hack
chris@3: }
chris@3:
chris@3: public long getPostingsCount()
chris@3: throws StorageBackendException
chris@3: {
chris@3: long postings = 0;
chris@3:
chris@3: for(GroupElement groupEl : groups)
chris@3: {
chris@3: postings += groupEl.group.getPostingsCount();
chris@3: }
chris@3:
chris@3: return postings;
chris@3: }
chris@3:
chris@3: public boolean isDeleted()
chris@3: {
chris@3: return false;
chris@3: }
chris@3:
chris@3: public boolean isWriteable()
chris@3: {
chris@3: return false;
chris@3: }
chris@3:
chris@3: }