EMMA Coverage Report (generated Tue Dec 09 03:51:57 CET 2014)
[all classes][org.jdtaus.banking.dtaus.ri.zka]

COVERAGE SUMMARY FOR SOURCE FILE [DefaultPhysicalFile.java]

nameclass, %method, %block, %line, %
DefaultPhysicalFile.java100% (2/2)100% (21/21)93%  (593/641)93%  (112.3/121)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DefaultPhysicalFile100% (1/1)100% (17/17)91%  (463/511)92%  (95.3/104)
DefaultPhysicalFile (int, FileOperations, Properties): void 100% (1/1)63%  (27/43)77%  (10/13)
get (int): LogicalFile 100% (1/1)64%  (9/14)67%  (2/3)
checksum (): void 100% (1/1)86%  (100/116)90%  (23.4/26)
checkLogicalFileExists (int): boolean 100% (1/1)90%  (9/10)90%  (0.9/1)
remove (int): void 100% (1/1)91%  (48/53)80%  (4/5)
newLogicalFile (long): AbstractLogicalFile 100% (1/1)94%  (83/88)95%  (18/19)
add (Header): LogicalFile 100% (1/1)100% (102/102)100% (16/16)
addLogicalFile (Header): LogicalFile 100% (1/1)100% (4/4)100% (1/1)
commit (): void 100% (1/1)100% (4/4)100% (2/2)
count (): int 100% (1/1)100% (3/3)100% (1/1)
getFileOperations (): FileOperations 100% (1/1)100% (3/3)100% (1/1)
getHeaderValidator (): HeaderValidator [] 100% (1/1)100% (7/7)100% (1/1)
getLogicalFile (int): LogicalFile 100% (1/1)100% (4/4)100% (1/1)
getLogicalFileCount (): int 100% (1/1)100% (3/3)100% (1/1)
getTaskMonitor (): TaskMonitor 100% (1/1)100% (6/6)100% (1/1)
removeLogicalFile (int): void 100% (1/1)100% (4/4)100% (2/2)
resizeIndex (int): void 100% (1/1)100% (47/47)100% (10/10)
     
class DefaultPhysicalFile$1100% (1/1)100% (4/4)100% (130/130)100% (17/17)
DefaultPhysicalFile$1 (DefaultPhysicalFile): void 100% (1/1)100% (6/6)100% (1/1)
bytesDeleted (long, long): void 100% (1/1)100% (46/46)100% (6/6)
bytesInserted (long, long): void 100% (1/1)100% (46/46)100% (6/6)
getFileIndex (long): int 100% (1/1)100% (32/32)100% (4/4)

1/*
2 *  jDTAUS Banking RI DTAUS
3 *  Copyright (C) 2005 Christian Schulte
4 *  <cs@schulte.it>
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Lesser General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2.1 of the License, or any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 *
20 */
21package org.jdtaus.banking.dtaus.ri.zka;
22 
23import java.io.IOException;
24import java.util.Iterator;
25import java.util.Map;
26import org.jdtaus.banking.dtaus.Checksum;
27import org.jdtaus.banking.dtaus.Header;
28import org.jdtaus.banking.dtaus.LogicalFile;
29import org.jdtaus.banking.dtaus.PhysicalFile;
30import org.jdtaus.banking.dtaus.PhysicalFileFactory;
31import org.jdtaus.banking.dtaus.spi.HeaderValidator;
32import org.jdtaus.banking.dtaus.spi.IllegalHeaderException;
33import org.jdtaus.banking.messages.AnalysesFileMessage;
34import org.jdtaus.core.container.ContainerFactory;
35import org.jdtaus.core.io.FileOperations;
36import org.jdtaus.core.monitor.spi.Task;
37import org.jdtaus.core.monitor.spi.TaskMonitor;
38 
39/**
40 * Default {@code PhysicalFile} implementation.
41 * <p><b>Note:</b><br/>
42 * This implementation is not thread-safe.</p>
43 *
44 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
45 * @version $JDTAUS: DefaultPhysicalFile.java 8661 2012-09-27 11:29:58Z schulte $
46 */
47public final class DefaultPhysicalFile implements PhysicalFile
48{
49 
50    /** Index der logischen Dateien. */
51    private AbstractLogicalFile[] index;
52 
53    /** Anzahl vorhandener logischer Dateien. */
54    private int dtausCount = 0;
55 
56    /** Mapping of attribute names to theire values. */
57    private final java.util.Properties properties;
58 
59    /** <code>FileOperations</code> requirement. **/
60    private FileOperations fileOperations;
61 
62    /** Format of this instance. */
63    private final int format;
64 
65    /**
66     * Creates a new {@code DefaultPhysicalFile} instance.
67     *
68     * @param format The format of the new instance.
69     * @param fileOperations The {@code FileOperations} implementation to operate on.
70     * @param properties Configuration properties.
71     *
72     * @throws NullPointerException if either {@code fileOperations} or {@code properties} is {@code null}.
73     * @throws IllegalArgumentException if {@code format} is not equal to {@code FORMAT_DISK} and {@code FORMAT_TAPE}.
74     * @throws IOException wenn nicht gelesen werden kann.
75     *
76     * @see PhysicalFileFactory#FORMAT_DISK
77     * @see PhysicalFileFactory#FORMAT_TAPE
78     */
79    public DefaultPhysicalFile(
80        final int format, final FileOperations fileOperations, final java.util.Properties properties )
81        throws IOException
82    {
83        super();
84 
85        if ( fileOperations == null )
86        {
87            throw new NullPointerException( "fileOperations" );
88        }
89        if ( properties == null )
90        {
91            throw new NullPointerException( "properties" );
92        }
93        if ( format != PhysicalFileFactory.FORMAT_DISK && format != PhysicalFileFactory.FORMAT_TAPE )
94        {
95            throw new IllegalArgumentException( Integer.toString( format ) );
96        }
97 
98        this.properties = properties;
99        this.fileOperations = fileOperations;
100        this.format = format;
101        this.checksum();
102    }
103 
104    public int count()
105    {
106        return this.dtausCount;
107    }
108 
109    public LogicalFile add( final Header header ) throws IOException
110    {
111        if ( header == null )
112        {
113            throw new NullPointerException( "header" );
114        }
115 
116        IllegalHeaderException result = null;
117        final HeaderValidator[] validators = this.getHeaderValidator();
118 
119        for ( int i = validators.length - 1; i >= 0; i-- )
120        {
121            result = validators[i].assertValidHeader( header, result );
122        }
123 
124        if ( result != null && result.getMessages().length > 0 )
125        {
126            throw result;
127        }
128 
129        this.resizeIndex( this.dtausCount );
130 
131        final AbstractLogicalFile lFile = this.newLogicalFile(
132            ( this.dtausCount == 0 ? 0L : this.index[this.dtausCount - 1].getChecksumPosition() +
133                                          this.index[this.dtausCount - 1].getBlockSize() ) );
134 
135        lFile.insertBytes( lFile.getHeaderPosition(), this.format * 2 );
136        lFile.writeHeader( header );
137        lFile.writeChecksum( new Checksum() );
138        lFile.checksum();
139        this.index[this.dtausCount] = lFile;
140        return this.index[this.dtausCount++];
141    }
142 
143    public LogicalFile get( int dtausId )
144    {
145        if ( !this.checkLogicalFileExists( dtausId ) )
146        {
147            throw new IllegalArgumentException( "dtausId" );
148        }
149        return this.index[dtausId];
150    }
151 
152    public void remove( int dtausId ) throws IOException
153    {
154        if ( !this.checkLogicalFileExists( dtausId ) )
155        {
156            throw new IllegalArgumentException( "dtausId" );
157        }
158 
159        this.index[dtausId].removeBytes(
160            this.index[dtausId].getHeaderPosition(), this.index[dtausId].getChecksumPosition() -
161                                                     this.index[dtausId].getHeaderPosition() + this.format );
162 
163        System.arraycopy( this.index, dtausId + 1, this.index, dtausId, --this.dtausCount - dtausId );
164    }
165 
166    public void commit() throws IOException
167    {
168        this.getFileOperations().close();
169    }
170 
171    public int getLogicalFileCount() throws IOException
172    {
173        return this.count();
174    }
175 
176    public LogicalFile addLogicalFile( final Header header ) throws IOException
177    {
178        return this.add( header );
179    }
180 
181    public LogicalFile getLogicalFile( final int index ) throws IOException
182    {
183        return this.get( index );
184    }
185 
186    public void removeLogicalFile( final int index ) throws IOException
187    {
188        this.remove( index );
189    }
190 
191    /** FileOperations requirement getter method. */
192    private FileOperations getFileOperations()
193    {
194        return this.fileOperations;
195    }
196 
197    private boolean checkLogicalFileExists( int dtausId )
198    {
199        return dtausId < this.dtausCount && dtausId >= 0;
200    }
201 
202    private void checksum() throws IOException
203    {
204        this.dtausCount = 0;
205        int dtausIndex = 0;
206        final long length = this.getFileOperations().getLength();
207        long maximumProgress = length;
208        long progressDivisor = 1L;
209 
210        while ( maximumProgress > Integer.MAX_VALUE )
211        {
212            maximumProgress /= 2L;
213            progressDivisor *= 2L;
214        }
215 
216        final Task task = new Task();
217        task.setIndeterminate( false );
218        task.setCancelable( false );
219        task.setDescription( new AnalysesFileMessage() );
220        task.setMinimum( 0 );
221        task.setProgress( 0 );
222        task.setMaximum( (int) maximumProgress );
223 
224        try
225        {
226            this.getTaskMonitor().monitor( task );
227 
228            for ( long position = 0L; position < length;
229                  position = this.index[dtausIndex].getChecksumPosition() + this.index[dtausIndex++].getBlockSize() )
230            {
231                task.setProgress( (int) ( position / progressDivisor ) );
232                this.resizeIndex( dtausIndex );
233                this.index[dtausIndex] = this.newLogicalFile( position );
234                this.index[dtausIndex].checksum();
235                this.dtausCount++;
236            }
237        }
238        finally
239        {
240            this.getTaskMonitor().finish( task );
241        }
242    }
243 
244    private AbstractLogicalFile newLogicalFile( final long headerPosition ) throws IOException
245    {
246        final AbstractLogicalFile ret;
247 
248        switch ( this.format )
249        {
250            case PhysicalFileFactory.FORMAT_DISK:
251                ret = new DTAUSDisk();
252                break;
253            case PhysicalFileFactory.FORMAT_TAPE:
254                ret = new DTAUSTape();
255                break;
256            default:
257                throw new IllegalStateException();
258 
259        }
260 
261        ret.setFileOperations( this.getFileOperations() );
262        ret.setHeaderPosition( headerPosition );
263        ret.setChecksumPosition( headerPosition + this.format );
264 
265        for ( Iterator it = this.properties.entrySet().iterator(); it.hasNext(); )
266        {
267            final Map.Entry e = (Map.Entry) it.next();
268            final String key = (String) e.getKey();
269 
270            if ( key.startsWith( DefaultPhysicalFileFactory.ATTRIBUTE_SPACE_CHARACTERS_ALLOWED ) )
271            {
272                int field = Integer.parseInt( key.substring( key.lastIndexOf( '.' ) + 1 ), 16 );
273                final boolean allowed =
274                    e.getValue() != null && Boolean.valueOf( e.getValue().toString() ).booleanValue();
275 
276                ret.getConfiguration().setSpaceCharacterAllowed( field, allowed );
277            }
278        }
279 
280        ret.addListener( new AbstractLogicalFile.Listener()
281        {
282 
283            public void bytesInserted( final long position, final long bytes ) throws IOException
284            {
285                final int fileIndex = this.getFileIndex( position );
286                if ( fileIndex >= 0 )
287                {
288                    // Increment properties headerPosition and checksumPosition for all remaining files.
289                    for ( int i = fileIndex + 1; i < dtausCount; i++ )
290                    {
291                        index[i].setHeaderPosition( index[i].getHeaderPosition() + bytes );
292                        index[i].setChecksumPosition( index[i].getChecksumPosition() + bytes );
293                    }
294                }
295            }
296 
297            public void bytesDeleted( final long position, final long bytes ) throws IOException
298            {
299                final int fileIndex = this.getFileIndex( position );
300                if ( fileIndex >= 0 )
301                {
302                    // Decrement properties headerPosition and checksumPosition for all remaining files.
303                    for ( int i = fileIndex + 1; i < dtausCount; i++ )
304                    {
305                        index[i].setHeaderPosition( index[i].getHeaderPosition() - bytes );
306                        index[i].setChecksumPosition( index[i].getChecksumPosition() - bytes );
307                    }
308                }
309            }
310 
311            private int getFileIndex( final long position )
312            {
313                for ( int i = dtausCount - 1; i >= 0; i-- )
314                {
315                    if ( position >= index[i].getHeaderPosition() && position <= index[i].getChecksumPosition() )
316                    {
317                        return i;
318                    }
319                }
320 
321                return -1;
322            }
323 
324        } );
325 
326        return ret;
327    }
328 
329    private void resizeIndex( int index )
330    {
331        if ( this.index == null )
332        {
333            this.index = new AbstractLogicalFile[ index + 1 ];
334        }
335        else if ( this.index.length < index + 1 )
336        {
337            while ( this.index.length < index + 1 )
338            {
339                final int newLength = this.index.length * 2;
340                final AbstractLogicalFile[] newIndex = new AbstractLogicalFile[ newLength ];
341                System.arraycopy( this.index, 0, newIndex, 0, this.index.length );
342                this.index = newIndex;
343            }
344        }
345    }
346 
347    //--Dependencies------------------------------------------------------------
348 
349// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
350    // This section is managed by jdtaus-container-mojo.
351 
352    /**
353     * Gets the configured <code>TaskMonitor</code> implementation.
354     *
355     * @return The configured <code>TaskMonitor</code> implementation.
356     */
357    private TaskMonitor getTaskMonitor()
358    {
359        return (TaskMonitor) ContainerFactory.getContainer().
360            getDependency( this, "TaskMonitor" );
361 
362    }
363 
364    /**
365     * Gets the configured <code>HeaderValidator</code> implementation.
366     *
367     * @return The configured <code>HeaderValidator</code> implementation.
368     */
369    private HeaderValidator[] getHeaderValidator()
370    {
371        return (HeaderValidator[]) ContainerFactory.getContainer().
372            getDependency( this, "HeaderValidator" );
373 
374    }
375 
376// </editor-fold>//GEN-END:jdtausDependencies
377 
378    //------------------------------------------------------------Dependencies--
379}

[all classes][org.jdtaus.banking.dtaus.ri.zka]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov