org/sonews/storage/AggregatedGroup.java
author cli
Thu Aug 20 14:31:19 2009 +0200 (2009-08-20)
changeset 12 bb6990c0dd1a
permissions -rw-r--r--
Merging fixes from sonews/1.0.3
     1 /*
     2  *   SONEWS News Server
     3  *   see AUTHORS for the list of contributors
     4  *
     5  *   This program is free software: you can redistribute it and/or modify
     6  *   it under the terms of the GNU General Public License as published by
     7  *   the Free Software Foundation, either version 3 of the License, or
     8  *   (at your option) any later version.
     9  *
    10  *   This program is distributed in the hope that it will be useful,
    11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  *   GNU General Public License for more details.
    14  *
    15  *   You should have received a copy of the GNU General Public License
    16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  */
    18 
    19 package org.sonews.storage;
    20 
    21 import java.util.ArrayList;
    22 import java.util.Collections;
    23 import java.util.List;
    24 import org.sonews.util.Pair;
    25 
    26 /**
    27  * An aggregated group is a group consisting of several "real" group.
    28  * @author Christian Lins
    29  * @since sonews/1.0
    30  */
    31 class AggregatedGroup extends Channel
    32 {
    33 
    34   static class GroupElement
    35   {
    36     private Group group;
    37     private long  offsetStart, offsetEnd;
    38     
    39     public GroupElement(Group group, long offsetStart, long offsetEnd)
    40     {
    41       this.group       = group;
    42       this.offsetEnd   = offsetEnd;
    43       this.offsetStart = offsetStart;
    44     }
    45   }
    46 
    47   public static List<Channel> getAll()
    48   {
    49     List<Channel> all = new ArrayList<Channel>();
    50     all.add(getByName("agg.test"));
    51     return all;
    52   }
    53 
    54   public static AggregatedGroup getByName(String name)
    55   {
    56     if("agg.test".equals(name))
    57     {
    58       AggregatedGroup agroup = new AggregatedGroup(name);
    59       agroup.addGroup(Group.getByName("agg.test0"), 0, 1000);
    60       agroup.addGroup(Group.getByName("agg.test1"), 2000, 4000);
    61       return agroup;
    62     }
    63     else
    64       return null;
    65   }
    66 
    67   private GroupElement[] groups = new GroupElement[2];
    68   private String         name;
    69 
    70   public AggregatedGroup(String name)
    71   {
    72     this.name = name;
    73   }
    74 
    75   private long aggIdxToIdx(long aggIdx)
    76     throws StorageBackendException
    77   {
    78     assert groups != null && groups.length == 2;
    79     assert groups[0] != null;
    80     assert groups[1] != null;
    81 
    82     // Search in indices of group one
    83     List<Long> idxs0 = groups[0].group.getArticleNumbers();
    84     Collections.sort(idxs0);
    85     for(long idx : idxs0)
    86     {
    87       if(idx == aggIdx)
    88       {
    89         return idx;
    90       }
    91     }
    92 
    93     // Given aggIdx must be an index of group two
    94     List<Long> idxs1 = groups[1].group.getArticleNumbers();
    95     return 0;
    96   }
    97   
    98   private long idxToAggIdx(long idx)
    99   {
   100     return 0;
   101   }
   102 
   103   /**
   104    * Adds the given group to this aggregated set.
   105    * @param group
   106    * @param offsetStart Lower limit for the article ids range
   107    */
   108   public void addGroup(Group group, long offsetStart, long offsetEnd)
   109   {
   110     this.groups[groups[0] == null ? 0 : 1]
   111       = new GroupElement(group, offsetStart, offsetEnd);
   112   }
   113 
   114   @Override
   115   public Article getArticle(long idx)
   116     throws StorageBackendException
   117   {
   118     Article article = null;
   119 
   120     for(GroupElement groupEl : groups)
   121     {
   122       if(groupEl.offsetStart <= idx && groupEl.offsetEnd >= idx)
   123       {
   124         article = groupEl.group.getArticle(idx - groupEl.offsetStart);
   125         break;
   126       }
   127     }
   128 
   129     return article;
   130   }
   131 
   132   @Override
   133   public List<Pair<Long, ArticleHead>> getArticleHeads(
   134     final long first, final long last)
   135     throws StorageBackendException
   136   {
   137     List<Pair<Long, ArticleHead>> heads = new ArrayList<Pair<Long, ArticleHead>>();
   138     
   139     for(GroupElement groupEl : groups)
   140     {
   141       List<Pair<Long, ArticleHead>> partHeads = new ArrayList<Pair<Long, ArticleHead>>();
   142       if(groupEl.offsetStart <= first && groupEl.offsetEnd >= first)
   143       {
   144         long end = Math.min(groupEl.offsetEnd, last);
   145         partHeads = groupEl.group.getArticleHeads
   146           (first - groupEl.offsetStart, end - groupEl.offsetStart);
   147       }
   148       else if(groupEl.offsetStart <= last && groupEl.offsetEnd >= last)
   149       {
   150         long start = Math.max(groupEl.offsetStart, first);
   151         partHeads = groupEl.group.getArticleHeads
   152           (start - groupEl.offsetStart, last - groupEl.offsetStart);
   153       }
   154 
   155       for(Pair<Long, ArticleHead> partHead : partHeads)
   156       {
   157         heads.add(new Pair<Long, ArticleHead>(
   158           partHead.getA() + groupEl.offsetStart, partHead.getB()));
   159       }
   160     }
   161 
   162     return heads;
   163   }
   164 
   165   @Override
   166   public List<Long> getArticleNumbers()
   167     throws StorageBackendException
   168   {
   169     List<Long> articleNumbers = new ArrayList<Long>();
   170     
   171     for(GroupElement groupEl : groups)
   172     {
   173       List<Long> partNums = groupEl.group.getArticleNumbers();
   174       for(Long partNum : partNums)
   175       {
   176         articleNumbers.add(partNum + groupEl.offsetStart);
   177       }
   178     }
   179 
   180     return articleNumbers;
   181   }
   182 
   183   @Override
   184   public long getIndexOf(Article art)
   185     throws StorageBackendException
   186   {
   187     for(GroupElement groupEl : groups)
   188     {
   189       long idx = groupEl.group.getIndexOf(art);
   190       if(idx > 0)
   191       {
   192         return idx;
   193       }
   194     }
   195     return -1;
   196   }
   197 
   198   public long getInternalID()
   199   {
   200     return -1;
   201   }
   202 
   203   @Override
   204   public String getName()
   205   {
   206     return this.name;
   207   }
   208 
   209   @Override
   210   public long getFirstArticleNumber()
   211     throws StorageBackendException
   212   {
   213     long first = Long.MAX_VALUE;
   214 
   215     for(GroupElement groupEl : groups)
   216     {
   217       first = Math.min(first, groupEl.group.getFirstArticleNumber() + groupEl.offsetStart);
   218     }
   219 
   220     return first;
   221   }
   222 
   223   @Override
   224   public long getLastArticleNumber()
   225     throws StorageBackendException
   226   {
   227     long last = 1;
   228 
   229     for(GroupElement groupEl : groups)
   230     {
   231       last = Math.max(last, groupEl.group.getLastArticleNumber() + groupEl.offsetStart);
   232     }
   233 
   234     return last + getPostingsCount(); // This is a hack
   235   }
   236   
   237   public long getPostingsCount()
   238     throws StorageBackendException
   239   {
   240     long postings = 0;
   241 
   242     for(GroupElement groupEl : groups)
   243     {
   244       postings += groupEl.group.getPostingsCount();
   245     }
   246 
   247     return postings;
   248   }
   249 
   250   public boolean isDeleted()
   251   {
   252     return false;
   253   }
   254 
   255   public boolean isWriteable()
   256   {
   257     return false;
   258   }
   259 
   260 }