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 }