001 /* 002 * Copyright 2002-2005 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016 package org.springframework.binding.value.support; 017 018 import java.io.ByteArrayInputStream; 019 import java.io.ByteArrayOutputStream; 020 import java.io.IOException; 021 import java.io.NotSerializableException; 022 import java.io.ObjectInputStream; 023 import java.io.ObjectOutputStream; 024 import java.util.ArrayList; 025 import java.util.Collection; 026 027 import org.springframework.binding.value.ValueModel; 028 029 /** 030 * Implementation of a BufferedCollectionValueModel that performs a deep copy on the 031 * elements of the collection. 032 * 033 * @author Larry Streepy 034 * 035 */ 036 public class DeepCopyBufferedCollectionValueModel extends BufferedCollectionValueModel { 037 038 /** 039 * Constructs a new DeepCopyBufferedCollectionValueModel. 040 * 041 * @param wrappedModel the value model to wrap 042 * @param wrappedType the class of the value contained by wrappedModel; this must be 043 * assignable to <code>java.util.Collection</code> or 044 * <code>Object[]</code>. 045 */ 046 public DeepCopyBufferedCollectionValueModel(ValueModel wrappedModel, Class wrappedType) { 047 super( wrappedModel, wrappedType ); 048 } 049 050 /** 051 * Prepare the backing collection for installation into the listListModel. Create a 052 * new collection that contains a deep copy of the elements in the given collection. 053 * 054 * @param col The collection of objects to process 055 * @return processed collection 056 */ 057 protected Collection prepareBackingCollection(Collection col) { 058 ArrayList list = new ArrayList(col); 059 for( int i=0; i < list.size(); i++ ) { 060 list.set(i, deepCopy(list.get(i))); 061 } 062 return list; 063 } 064 065 /** 066 * Create a new object that is a deep copy of the given object. This copy is created 067 * using serialization, so the object to be copied must implement Serializable. If it 068 * does not, then the original object will be returned. Any other error results in 069 * null being returned. 070 * 071 * @param value 072 * @return deep copy 073 */ 074 protected Object deepCopy(Object value) { 075 try { 076 // Write to new byte array to clone. 077 ByteArrayOutputStream baos = new ByteArrayOutputStream( 1024 ); 078 ObjectOutputStream oos = new ObjectOutputStream( baos ); 079 try { 080 oos.writeObject( value ); 081 } catch( NotSerializableException e ) { 082 return value; 083 } finally { 084 oos.close(); 085 } 086 087 // Read it back and return a true copy. 088 ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() ); 089 ObjectInputStream ois = new ObjectInputStream( bais ); 090 try { 091 return ois.readObject(); 092 } finally { 093 ois.close(); 094 } 095 } catch( ClassNotFoundException ex ) { 096 ex.printStackTrace(); 097 } catch( IOException ex ) { 098 ex.printStackTrace(); 099 } 100 return null; 101 } 102 }