KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > poifs > storage > SmallDocumentBlock


1
2 /* ====================================================================
3    Copyright 2002-2004 Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 ==================================================================== */

17         
18
19 package org.apache.poi.poifs.storage;
20
21 import java.io.*;
22
23 import java.util.*;
24
25 import org.apache.poi.poifs.common.POIFSConstants;
26
27 /**
28  * Storage for documents that are too small to use regular
29  * DocumentBlocks for their data
30  *
31  * @author Marc Johnson (mjohnson at apache dot org)
32  */

33
34 public class SmallDocumentBlock
35     implements BlockWritable, ListManagedBlock
36 {
37     private byte[] _data;
38     private static final byte _default_fill = ( byte ) 0xff;
39     private static final int _block_size = 64;
40     private static final int _blocks_per_big_block =
41         POIFSConstants.BIG_BLOCK_SIZE / _block_size;
42
43     private SmallDocumentBlock(final byte [] data, final int index)
44     {
45         this();
46         System.arraycopy(data, index * _block_size, _data, 0, _block_size);
47     }
48
49     private SmallDocumentBlock()
50     {
51         _data = new byte[ _block_size ];
52     }
53
54     /**
55      * convert a single long array into an array of SmallDocumentBlock
56      * instances
57      *
58      * @param array the byte array to be converted
59      * @param size the intended size of the array (which may be smaller)
60      *
61      * @return an array of SmallDocumentBlock instances, filled from
62      * the array
63      */

64
65     public static SmallDocumentBlock [] convert(final byte [] array,
66                                                 final int size)
67     {
68         SmallDocumentBlock[] rval =
69             new SmallDocumentBlock[ (size + _block_size - 1) / _block_size ];
70         int offset = 0;
71
72         for (int k = 0; k < rval.length; k++)
73         {
74             rval[ k ] = new SmallDocumentBlock();
75             if (offset < array.length)
76             {
77                 int length = Math.min(_block_size, array.length - offset);
78
79                 System.arraycopy(array, offset, rval[ k ]._data, 0, length);
80                 if (length != _block_size)
81                 {
82                     Arrays.fill(rval[ k ]._data, length, _block_size,
83                                 _default_fill);
84                 }
85             }
86             else
87             {
88                 Arrays.fill(rval[ k ]._data, _default_fill);
89             }
90             offset += _block_size;
91         }
92         return rval;
93     }
94
95     /**
96      * fill out a List of SmallDocumentBlocks so that it fully occupies
97      * a set of big blocks
98      *
99      * @param blocks the List to be filled out
100      *
101      * @return number of big blocks the list encompasses
102      */

103
104     public static int fill(final List blocks)
105     {
106         int count = blocks.size();
107         int big_block_count = (count + _blocks_per_big_block - 1)
108                               / _blocks_per_big_block;
109         int full_count = big_block_count * _blocks_per_big_block;
110
111         for (; count < full_count; count++)
112         {
113             blocks.add(makeEmptySmallDocumentBlock());
114         }
115         return big_block_count;
116     }
117
118     /**
119      * Factory for creating SmallDocumentBlocks from DocumentBlocks
120      *
121      * @param store the original DocumentBlocks
122      * @param size the total document size
123      *
124      * @return an array of new SmallDocumentBlocks instances
125      *
126      * @exception IOException on errors reading from the DocumentBlocks
127      * @exception ArrayIndexOutOfBoundsException if, somehow, the store
128      * contains less data than size indicates
129      */

130
131     public static SmallDocumentBlock [] convert(final BlockWritable [] store,
132                                                 final int size)
133         throws IOException, ArrayIndexOutOfBoundsException JavaDoc
134     {
135         ByteArrayOutputStream stream = new ByteArrayOutputStream();
136
137         for (int j = 0; j < store.length; j++)
138         {
139             store[ j ].writeBlocks(stream);
140         }
141         byte[] data = stream.toByteArray();
142         SmallDocumentBlock[] rval =
143             new SmallDocumentBlock[ convertToBlockCount(size) ];
144
145         for (int index = 0; index < rval.length; index++)
146         {
147             rval[ index ] = new SmallDocumentBlock(data, index);
148         }
149         return rval;
150     }
151
152     /**
153      * create a list of SmallDocumentBlock's from raw data
154      *
155      * @param blocks the raw data containing the SmallDocumentBlock
156      * data
157      *
158      * @return a List of SmallDocumentBlock's extracted from the input
159      *
160      * @exception IOException
161      */

162
163     public static List extract(ListManagedBlock [] blocks)
164         throws IOException
165     {
166         List sdbs = new ArrayList();
167
168         for (int j = 0; j < blocks.length; j++)
169         {
170             byte[] data = blocks[ j ].getData();
171
172             for (int k = 0; k < _blocks_per_big_block; k++)
173             {
174                 sdbs.add(new SmallDocumentBlock(data, k));
175             }
176         }
177         return sdbs;
178     }
179
180     /**
181      * read data from an array of SmallDocumentBlocks
182      *
183      * @param blocks the blocks to read from
184      * @param buffer the buffer to write the data into
185      * @param offset the offset into the array of blocks to read from
186      */

187
188     public static void read(final BlockWritable [] blocks,
189                             final byte [] buffer, final int offset)
190     {
191         int firstBlockIndex = offset / _block_size;
192         int firstBlockOffset = offset % _block_size;
193         int lastBlockIndex = (offset + buffer.length - 1) / _block_size;
194
195         if (firstBlockIndex == lastBlockIndex)
196         {
197             System.arraycopy(
198                 (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data,
199                 firstBlockOffset, buffer, 0, buffer.length);
200         }
201         else
202         {
203             int buffer_offset = 0;
204
205             System.arraycopy(
206                 (( SmallDocumentBlock ) blocks[ firstBlockIndex ])._data,
207                 firstBlockOffset, buffer, buffer_offset,
208                 _block_size - firstBlockOffset);
209             buffer_offset += _block_size - firstBlockOffset;
210             for (int j = firstBlockIndex + 1; j < lastBlockIndex; j++)
211             {
212                 System.arraycopy((( SmallDocumentBlock ) blocks[ j ])._data,
213                                  0, buffer, buffer_offset, _block_size);
214                 buffer_offset += _block_size;
215             }
216             System.arraycopy(
217                 (( SmallDocumentBlock ) blocks[ lastBlockIndex ])._data, 0,
218                 buffer, buffer_offset, buffer.length - buffer_offset);
219         }
220     }
221
222     /**
223      * Calculate the storage size of a set of SmallDocumentBlocks
224      *
225      * @param size number of SmallDocumentBlocks
226      *
227      * @return total size
228      */

229
230     public static int calcSize(int size)
231     {
232         return size * _block_size;
233     }
234
235     private static SmallDocumentBlock makeEmptySmallDocumentBlock()
236     {
237         SmallDocumentBlock block = new SmallDocumentBlock();
238
239         Arrays.fill(block._data, _default_fill);
240         return block;
241     }
242
243     private static int convertToBlockCount(final int size)
244     {
245         return (size + _block_size - 1) / _block_size;
246     }
247
248     /* ********** START implementation of BlockWritable ********** */
249
250     /**
251      * Write the storage to an OutputStream
252      *
253      * @param stream the OutputStream to which the stored data should
254      * be written
255      *
256      * @exception IOException on problems writing to the specified
257      * stream
258      */

259
260     public void writeBlocks(final OutputStream stream)
261         throws IOException
262     {
263         stream.write(_data);
264     }
265
266     /* ********** END implementation of BlockWritable ********** */
267     /* ********** START implementation of ListManagedBlock ********** */
268
269     /**
270      * Get the data from the block
271      *
272      * @return the block's data as a byte array
273      *
274      * @exception IOException if there is no data
275      */

276
277     public byte [] getData()
278         throws IOException
279     {
280         return _data;
281     }
282
283     /* ********** END implementation of ListManagedBlock ********** */
284 } // end public class SmallDocumentBlock
285

286
Popular Tags