Bug 27333 - Cannot clone HSSFCellStyle
Summary: Cannot clone HSSFCellStyle
Status: RESOLVED FIXED
Alias: None
Product: POI
Classification: Unclassified
Component: HSSF (show other bugs)
Version: 2.0-FINAL
Hardware: PC All
: P3 normal (vote)
Target Milestone: ---
Assignee: POI Developers List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-03-01 13:18 UTC by Tim Wilkins
Modified: 2009-01-05 13:59 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tim Wilkins 2004-03-01 13:18:21 UTC
HSSFCellStyle does not implement Cloneable and has no 'clone()' method.

I think it is important to make HSSFCellStyle clonable as I think it will be
quite common that users will want to be able to take an existing style and
modify a copy of it rather than trying to create a similar style from scratch
which is a pain in the butt.

Also it is very little work to implement this! :)
Comment 1 Andy Oliver 2004-03-01 20:08:20 UTC
HSSFCellStyle is a reference to something in the Workbook.  HSSFCellStyle should
not be cloned, instead you should get instances from the workbook (which should
be cloneable).  Think of HSSFCellStyle as a "reference" and what is the point of
"cloning" a reference.
Comment 2 Tim Wilkins 2004-03-02 09:43:58 UTC
Sorry Andy, I made a mistake with my original request. You are right that there
is no point in cloning a reference. What I needed to achieve is a deep copy of
the HSSFCellStyle which I mistakenly thought implementing the clone method would
do (sorry my mistake).

I have successfully implemented a deep copy via serialisation of the
HSSFCellStyle object. However to do this I have had to make the following
classes implement the "java.io.Serializable" class:

org.apache.poi.hssf.usermodel.HSSFCell
org.apache.poi.hssf.usermodel.HSSFCellStyle
org.apache.poi.hssf.record.Record

The last class "org.apache.poi.hssf.record.Record" I altered so that all Record
sub-classes would also be serialisable as a result although the only class in
the "org.apache.poi.hssf.record" package I actually needed to be serialisable
for my purposes is "org.apache.poi.hssf.record.ExtendedFormatRecord".

Would it be acceptable to add these changes to the next release, again it is
very little work and would be a great help to me.

Cheers,

Tim


Comment 3 Amol Deshmukh 2005-01-21 15:43:39 UTC
(In reply to comment #2)
> Sorry Andy, I made a mistake with my original request. You are right that there
> is no point in cloning a reference. What I needed to achieve is a deep copy of
> the HSSFCellStyle which I mistakenly thought implementing the clone method would
> do (sorry my mistake).
> 
> I have successfully implemented a deep copy via serialisation of the
> HSSFCellStyle object. However to do this I have had to make the following
> classes implement the "java.io.Serializable" class:
> 
> org.apache.poi.hssf.usermodel.HSSFCell
> org.apache.poi.hssf.usermodel.HSSFCellStyle
> org.apache.poi.hssf.record.Record
> 
> The last class "org.apache.poi.hssf.record.Record" I altered so that all Record
> sub-classes would also be serialisable as a result although the only class in
> the "org.apache.poi.hssf.record" package I actually needed to be serialisable
> for my purposes is "org.apache.poi.hssf.record.ExtendedFormatRecord".
> 
> Would it be acceptable to add these changes to the next release, again it is
> very little work and would be a great help to me.
> 
> Cheers,
> 
> Tim
> 
> 
> 



Another way to tackle it outside of POI source is to create javabean classes for
HSSFCellStyle, HSSFFont and HSSFCellFormat. Make these javabean classes have the
same set/get methods as the corresponding hssf classes but make them Cloneable,
Serializable etc. And provide a method on each of these that takes in a
HSSFWorkbook and returns a new javabean object. (I have avoided Cloneable since
it is considered to be a flawed method, I use explicity method named makeCopy()
that returns a new copy). Make a factory that returns preconfigured instances of
style/font/format javabeans.

Finally, extend HSSFWorkbook class (create a decorator) to cache the actual
styles created in a Map, and provide a method geetOrCreateCellStyle(String name)
etc. which first checks in the cache for styles by this name previously created
in this workbook and returns the same or creates one using javabean instances
from the factory if map lookup fails.

Foll is the outline of this code:

//-- Wrapper for hssfcellstyle
public class CellStyleBean implements Serializable {
    protected short borderBottom;
    // all other similar fields
    protected short preferredCellWidth;
    public HSSFCellStyle toCellStyle(HSSFWorkbook workbook) {
        HSSFCellStyle retval = workbook.createCellStyle();
        retval.setAlignment(alignment);
        // other setters
        retval.setWrapText(wrapText);
        return retval;
    }
    public CellStyleProps makeCopy() {
        CellStyleProps retval = new CellStyleProps();
        retval.setAlignment(alignment);
        // other setters here
        retval.setPreferredCellWidth(preferredCellWidth);
        return retval;
    }
    public short getAlignment() {
        return alignment;
    }
    public void setAlignment(short alignment) {
        this.alignment = alignment;
    }
    // other get/set
} // end of CellStyleBean



// --
// -- HSSFWorkbookDecorator class
// --
public class HSSFWorkbookDecorator extends HSSFWorkbook {
    protected Map cellStylesMap = new HashMap();
    protected Map fontsMap = new HashMap();
    protected Map dataFormatsMap = new HashMap();
    // provide all required constructors 
    //    and delegate all to super class
    public HSSFCellStyle getOrCreateCellStyle(String name) {
        HSSFCellStyle retval = (HSSFCellStyle) cellStylesMap.get(name);
        if (retval == null) {
            CellStyleProps cellStyleProps =
FormatFactory.getInstance().getCellStyleProps(name);
            if (cellStyleProps==null) {
                cellStyleProps = new CellStyleProps();   
            }
            retval = cellStyleProps.toCellStyle(this);
            cellStylesMap.put(name, retval);
        }
        return retval;
    }
    // simlar to above provide getOrCreateXYZ for font and dataformat
}
Comment 4 Josh Micich 2009-01-05 13:59:46 UTC
It looks like HSSFCellStyle.cloneStyleFrom(CellStyle) has the desired functionality.  This was added in svn r676205 (prior to release 3.1.1-alpha1).

Implementing Cloneable was probably decided against because cloning styles involves some updates to the workbook and other objects, and that might be considered beyond the expected complexity of Object.clone().

Please re-open this bug if the new method does not work as expected.