001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.store.model; 019 020 import java.io.Serializable; 021 import java.util.Collections; 022 import java.util.Date; 023 import java.util.HashMap; 024 import java.util.Map; 025 026 /** 027 * <p> 028 * Container holding the values of a persistent object. 029 * </p> 030 * <p> 031 * Objects to be stored in the database, are first represented by an instance of {@link ObjectContainer} and 032 * then serialised into a byte-array, which is finally encrypted and put into a {@link DataEntry}'s {@link DataEntry#getValue() value}. 033 * </p> 034 * <p> 035 * Note, that references to other objects 036 * are either not stored at all (in a "mapped-by"-relationship) or stored via the other object's 037 * {@link DataEntry#getDataEntryID() dataEntryID}; a persistent object is never stored as-is. 038 * </p> 039 * 040 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 041 */ 042 public class ObjectContainer 043 implements Serializable, Cloneable 044 { 045 private static final long serialVersionUID = 4L; 046 047 /** 048 * Stores the concrete value of a field mapped by the persistent {@link FieldMeta#getFieldID() fieldID}. 049 * If the value originally was a persistable object, it is replaced by its object-ID. 050 */ 051 private Map<Long, Object> fieldID2value = new HashMap<Long, Object>(); 052 053 private Object version; 054 055 public ObjectContainer() { } 056 057 // TODO maybe do custom serialisation/deserialisation in order to better keep compatibility? Or should we maybe instead use 058 // ObjectContainer2, ObjectContainer3 etc. (i.e. other classes)? 059 // private void writeObject(java.io.ObjectOutputStream out) 060 // throws IOException 061 // { 062 // out.defaultWriteObject(); 063 // } 064 // 065 // private void readObject(java.io.ObjectInputStream in) 066 // throws IOException, ClassNotFoundException 067 // { 068 // in.defaultReadObject(); 069 // } 070 // 071 // @SuppressWarnings("unused") // this method seems to be so new to Java that the Eclipse compiler doesn't know it yet and shows a warning. 072 // private void readObjectNoData() 073 // throws ObjectStreamException 074 // { 075 // // no special handling necessary 076 // } 077 078 /** 079 * Get a value. 080 * @param fieldID the field's persistent ID, i.e. a reference to {@link FieldMeta#getFieldID() FieldMeta.fieldID}. 081 * @return the value or <code>null</code>. 082 */ 083 public Object getValue(long fieldID) 084 { 085 return fieldID2value.get(fieldID); 086 } 087 088 /** 089 * Set a value. 090 * @param fieldID the field's persistent ID, i.e. a reference to {@link FieldMeta#getFieldID() FieldMeta.fieldID}. 091 * @param value either the raw value or the object-ID of a persistable object. Persistable objects are never stored 092 * directly in an <code>ObjectContainer</code>. 093 */ 094 public void setValue(long fieldID, Object value) 095 { 096 if (value == null) 097 fieldID2value.remove(fieldID); 098 else 099 fieldID2value.put(fieldID, value); 100 } 101 102 public Map<Long, Object> getFieldID2value() { 103 return Collections.unmodifiableMap(fieldID2value); 104 } 105 106 /** 107 * Get the object's version or <code>null</code>, if the persistence-capable class has no versioning enabled. 108 * The version can be a {@link Long}, a {@link Date} or anything else supported by DataNucleus/JDO. 109 * @return the object's version or <code>null</code>. 110 */ 111 public Object getVersion() { 112 return version; 113 } 114 public void setVersion(Object version) { 115 this.version = version; 116 } 117 118 @Override 119 public ObjectContainer clone() 120 { 121 ObjectContainer clone; 122 try { 123 clone = (ObjectContainer) super.clone(); 124 } catch (CloneNotSupportedException e) { 125 throw new RuntimeException(e); // should never happen => wrap as RuntimeException! 126 } 127 clone.fieldID2value = new HashMap<Long, Object>(this.fieldID2value); 128 return clone; 129 } 130 }