View Javadoc

1   package net.sf.logdistiller;
2   
3   /*
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  import java.io.IOException;
18  import java.text.ParseException;
19  import java.util.*;
20  
21  /**
22   * Combines logevents fetched from multiple factories. The resulting factory chooses the next logevent according to the
23   * order provided.
24   */
25  public class FactoryMultiplexer
26      extends LogEvent.Factory
27  {
28      private final Comparator logeventComparator;
29  
30      private final List factories = new ArrayList();
31  
32      private boolean initialized = false;
33  
34      private Comparator entryComparator;
35  
36      public FactoryMultiplexer( LogType.Description description )
37      {
38          this( description, null );
39      }
40  
41      public FactoryMultiplexer( LogType.Description description, Comparator logeventComparator )
42      {
43          super( description, "multiplexer" );
44          this.logeventComparator = logeventComparator;
45      }
46  
47      public void addFactory( LogEvent.Factory factory )
48      {
49          if ( initialized )
50          {
51              throw new IllegalStateException( "cannot add a new LogEvent.Factory after reading first event" );
52          }
53          if ( description != factory.getDescription() )
54          {
55              throw new IllegalArgumentException( "cannot add a new LogEvent.Factory with different description" );
56          }
57          factories.add( new Entry( factory ) );
58      }
59  
60      protected LogEvent readNextEvent()
61          throws IOException, ParseException
62      {
63          if ( !initialized )
64          {
65              init();
66          }
67          if ( factories.size() <= 0 )
68          {
69              return null;
70          }
71          Entry entry = (Entry) factories.get( 0 );
72          LogEvent nextEvent = entry.getEvent();
73          if ( entry.nextEvent() == null )
74          {
75              factories.remove( 0 );
76          }
77          else
78          {
79              sort();
80          }
81          return nextEvent;
82      }
83  
84      /**
85       * Initialize the multiplexer: fetch first event in each factory, remove empty factories, init entry comparator and
86       * sort the factories.
87       *
88       * @throws IOException
89       * @throws ParseException
90       */
91      private void init()
92          throws IOException, ParseException
93      {
94          initialized = true;
95          LogEvent oneEvent = null;
96          // fetch the first LogEvent
97          List emptyFactories = new ArrayList();
98          Iterator iter = factories.iterator();
99          while ( iter.hasNext() )
100         {
101             Entry entry = (Entry) iter.next();
102             LogEvent event = entry.nextEvent();
103             if ( event == null )
104             {
105                 emptyFactories.add( entry );
106             }
107             else
108             {
109                 oneEvent = event;
110             }
111         }
112         // remove empty factories
113         factories.removeAll( emptyFactories );
114         if ( factories.size() >= 0 )
115         {
116             // init entry comparator
117             if ( logeventComparator != null )
118             {
119                 entryComparator = new EntrySpecificComparator( logeventComparator );
120             }
121             else if ( oneEvent instanceof Comparable )
122             {
123                 entryComparator = new EntryNaturalComparator();
124             }
125             // sort the factories
126             sort();
127         }
128     }
129 
130     /**
131      * Sort the factories, if necessary (a logevent comparator has been provided, or logevent implements Comparable).
132      */
133     private void sort()
134     {
135         if ( entryComparator != null )
136         {
137             Collections.sort( factories, entryComparator );
138         }
139     }
140 
141     private static class Entry
142     {
143         protected LogEvent nextEvent;
144 
145         private final LogEvent.Factory factory;
146 
147         public Entry( LogEvent.Factory factory )
148         {
149             this.factory = factory;
150         }
151 
152         public LogEvent getEvent()
153         {
154             return nextEvent;
155         }
156 
157         public LogEvent nextEvent()
158             throws IOException, ParseException
159         {
160             nextEvent = factory.nextEvent();
161             return nextEvent;
162         }
163     }
164 
165     /**
166      * Comparator for entries with logevents that implement Comparable.
167      */
168     private static class EntryNaturalComparator
169         implements Comparator
170     {
171         public int compare( Object object1, Object object2 )
172         {
173             Entry entry1 = (Entry) object1;
174             Entry entry2 = (Entry) object2;
175             return ( (Comparable) entry1.getEvent() ).compareTo( entry2.getEvent() );
176         }
177     }
178 
179     /**
180      * Comparator for entries when a specific logevent Comparator is provided.
181      */
182     private static class EntrySpecificComparator
183         implements Comparator
184     {
185         private final Comparator eventComparator;
186 
187         public EntrySpecificComparator( Comparator eventComparator )
188         {
189             this.eventComparator = eventComparator;
190         }
191 
192         public int compare( Object object1, Object object2 )
193         {
194             Entry entry1 = (Entry) object1;
195             Entry entry2 = (Entry) object2;
196             return eventComparator.compare( entry1.getEvent(), entry2.getEvent() );
197         }
198     }
199 }