| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| package org.apache.poi.hssf.record.aggregates; |
| |
| import org.apache.poi.hssf.record.Record; |
| import org.apache.poi.hssf.record.RecordBase; |
| |
| /** |
| * <tt>RecordAggregate</tt>s are groups of of BIFF <tt>Record</tt>s that are typically stored |
| * together and/or updated together. Workbook / Sheet records are typically stored in a sequential |
| * list, which does not provide much structure to coordinate updates. |
| */ |
| public abstract class RecordAggregate extends RecordBase { |
| |
| /** |
| * Visit each of the atomic BIFF records contained in this {@link RecordAggregate} in the order |
| * that they should be written to file. Implementors may or may not return the actual |
| * {@link Record}s being used to manage POI's internal implementation. Callers should not |
| * assume either way, and therefore only attempt to modify those {@link Record}s after cloning |
| * |
| * @param rv The visitor to use for callbacks while walking this object |
| */ |
| public abstract void visitContainedRecords(RecordVisitor rv); |
| |
| public final int serialize(int offset, byte[] data) { |
| SerializingRecordVisitor srv = new SerializingRecordVisitor(data, offset); |
| visitContainedRecords(srv); |
| return srv.countBytesWritten(); |
| } |
| public int getRecordSize() { |
| RecordSizingVisitor rsv = new RecordSizingVisitor(); |
| visitContainedRecords(rsv); |
| return rsv.getTotalSize(); |
| } |
| |
| public interface RecordVisitor { |
| /** |
| * Implementors may call non-mutating methods on Record r. |
| * @param r must not be <code>null</code> |
| */ |
| void visitRecord(org.apache.poi.hssf.record.Record r); |
| } |
| |
| private static final class SerializingRecordVisitor implements RecordVisitor { |
| |
| private final byte[] _data; |
| private final int _startOffset; |
| private int _countBytesWritten; |
| |
| public SerializingRecordVisitor(byte[] data, int startOffset) { |
| _data = data; |
| _startOffset = startOffset; |
| _countBytesWritten = 0; |
| } |
| public int countBytesWritten() { |
| return _countBytesWritten; |
| } |
| public void visitRecord(org.apache.poi.hssf.record.Record r) { |
| int currentOffset = _startOffset + _countBytesWritten; |
| _countBytesWritten += r.serialize(currentOffset, _data); |
| } |
| } |
| private static final class RecordSizingVisitor implements RecordVisitor { |
| |
| private int _totalSize; |
| |
| public RecordSizingVisitor() { |
| _totalSize = 0; |
| } |
| public int getTotalSize() { |
| return _totalSize; |
| } |
| public void visitRecord(org.apache.poi.hssf.record.Record r) { |
| _totalSize += r.getRecordSize(); |
| } |
| } |
| /** |
| * A wrapper for {@link RecordVisitor} which accumulates the sizes of all |
| * records visited. |
| */ |
| public static final class PositionTrackingVisitor implements RecordVisitor { |
| private final RecordVisitor _rv; |
| private int _position; |
| |
| public PositionTrackingVisitor(RecordVisitor rv, int initialPosition) { |
| _rv = rv; |
| _position = initialPosition; |
| } |
| public void visitRecord(org.apache.poi.hssf.record.Record r) { |
| _position += r.getRecordSize(); |
| _rv.visitRecord(r); |
| } |
| public void setPosition(int position) { |
| _position = position; |
| } |
| public int getPosition() { |
| return _position; |
| } |
| } |
| } |