diff -r 000000000000 -r ad210aa137a4 org/sonews/storage/AggregatedGroup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org/sonews/storage/AggregatedGroup.java Thu Aug 06 18:34:10 2009 +0200 @@ -0,0 +1,260 @@ +/* + * SONEWS News Server + * see AUTHORS for the list of contributors + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +package org.sonews.storage; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.sonews.util.Pair; + +/** + * An aggregated group is a group consisting of several "real" group. + * @author Christian Lins + * @since sonews/1.0 + */ +class AggregatedGroup extends Channel +{ + + static class GroupElement + { + private Group group; + private long offsetStart, offsetEnd; + + public GroupElement(Group group, long offsetStart, long offsetEnd) + { + this.group = group; + this.offsetEnd = offsetEnd; + this.offsetStart = offsetStart; + } + } + + public static List getAll() + { + List all = new ArrayList(); + all.add(getByName("agg.test")); + return all; + } + + public static AggregatedGroup getByName(String name) + { + if("agg.test".equals(name)) + { + AggregatedGroup agroup = new AggregatedGroup(name); + agroup.addGroup(Group.getByName("agg.test0"), 0, 1000); + agroup.addGroup(Group.getByName("agg.test1"), 2000, 4000); + return agroup; + } + else + return null; + } + + private GroupElement[] groups = new GroupElement[2]; + private String name; + + public AggregatedGroup(String name) + { + this.name = name; + } + + private long aggIdxToIdx(long aggIdx) + throws StorageBackendException + { + assert groups != null && groups.length == 2; + assert groups[0] != null; + assert groups[1] != null; + + // Search in indices of group one + List idxs0 = groups[0].group.getArticleNumbers(); + Collections.sort(idxs0); + for(long idx : idxs0) + { + if(idx == aggIdx) + { + return idx; + } + } + + // Given aggIdx must be an index of group two + List idxs1 = groups[1].group.getArticleNumbers(); + return 0; + } + + private long idxToAggIdx(long idx) + { + return 0; + } + + /** + * Adds the given group to this aggregated set. + * @param group + * @param offsetStart Lower limit for the article ids range + */ + public void addGroup(Group group, long offsetStart, long offsetEnd) + { + this.groups[groups[0] == null ? 0 : 1] + = new GroupElement(group, offsetStart, offsetEnd); + } + + @Override + public Article getArticle(long idx) + throws StorageBackendException + { + Article article = null; + + for(GroupElement groupEl : groups) + { + if(groupEl.offsetStart <= idx && groupEl.offsetEnd >= idx) + { + article = groupEl.group.getArticle(idx - groupEl.offsetStart); + break; + } + } + + return article; + } + + @Override + public List> getArticleHeads( + final long first, final long last) + throws StorageBackendException + { + List> heads = new ArrayList>(); + + for(GroupElement groupEl : groups) + { + List> partHeads = new ArrayList>(); + if(groupEl.offsetStart <= first && groupEl.offsetEnd >= first) + { + long end = Math.min(groupEl.offsetEnd, last); + partHeads = groupEl.group.getArticleHeads + (first - groupEl.offsetStart, end - groupEl.offsetStart); + } + else if(groupEl.offsetStart <= last && groupEl.offsetEnd >= last) + { + long start = Math.max(groupEl.offsetStart, first); + partHeads = groupEl.group.getArticleHeads + (start - groupEl.offsetStart, last - groupEl.offsetStart); + } + + for(Pair partHead : partHeads) + { + heads.add(new Pair( + partHead.getA() + groupEl.offsetStart, partHead.getB())); + } + } + + return heads; + } + + @Override + public List getArticleNumbers() + throws StorageBackendException + { + List articleNumbers = new ArrayList(); + + for(GroupElement groupEl : groups) + { + List partNums = groupEl.group.getArticleNumbers(); + for(Long partNum : partNums) + { + articleNumbers.add(partNum + groupEl.offsetStart); + } + } + + return articleNumbers; + } + + @Override + public long getIndexOf(Article art) + throws StorageBackendException + { + for(GroupElement groupEl : groups) + { + long idx = groupEl.group.getIndexOf(art); + if(idx > 0) + { + return idx; + } + } + return -1; + } + + public long getInternalID() + { + return -1; + } + + @Override + public String getName() + { + return this.name; + } + + @Override + public long getFirstArticleNumber() + throws StorageBackendException + { + long first = Long.MAX_VALUE; + + for(GroupElement groupEl : groups) + { + first = Math.min(first, groupEl.group.getFirstArticleNumber() + groupEl.offsetStart); + } + + return first; + } + + @Override + public long getLastArticleNumber() + throws StorageBackendException + { + long last = 1; + + for(GroupElement groupEl : groups) + { + last = Math.max(last, groupEl.group.getLastArticleNumber() + groupEl.offsetStart); + } + + return last + getPostingsCount(); // This is a hack + } + + public long getPostingsCount() + throws StorageBackendException + { + long postings = 0; + + for(GroupElement groupEl : groups) + { + postings += groupEl.group.getPostingsCount(); + } + + return postings; + } + + public boolean isDeleted() + { + return false; + } + + public boolean isWriteable() + { + return false; + } + +}