| package org.apache.ode.bpel.obj; |
| |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.io.Serializable; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| |
| import org.apache.ode.bpel.obj.serde.jacksonhack.UniqueStringIdGenerator; |
| |
| import com.fasterxml.jackson.annotation.JsonIdentityInfo; |
| import com.fasterxml.jackson.annotation.JsonIgnore; |
| |
| @JsonIdentityInfo(generator = UniqueStringIdGenerator.class, property = "@id") |
| public class ExtensibleImpl implements Extensible<Object>, Serializable{ |
| public static final long serialVersionUID = -1L; |
| public static final int CURRENT_CLASS_VERSION = 1; |
| |
| /** The wrapper wraps fields. Fields can be deleted, added or updated */ |
| transient protected Map<String, Object> fieldContainer; |
| /** Version of this class*/ |
| private static final String CLASSVERSION = "classVersion"; |
| /** Original version before migration*/ |
| private static final String ORIGINALVERSION = "originalVersion"; |
| |
| protected ExtensibleImpl() { |
| this(new LinkedHashMap<String, Object>()); |
| } |
| protected ExtensibleImpl(Map<String, Object> container) { |
| fieldContainer = container; |
| int currentVersion = 0; |
| try { |
| currentVersion = (Integer) this.getClass().getField("CURRENT_CLASS_VERSION").get(this); |
| } catch (Exception e) { |
| // should never get here |
| e.printStackTrace(); |
| } |
| setClassVersion(currentVersion); |
| setOriginalVersion(currentVersion); //if this is called by deserializer, original will be set later. |
| } |
| |
| // @JsonAnyGetter |
| public Map<String, Object> getFieldContainer() { |
| return fieldContainer; |
| } |
| public void setFieldContainer(Map<String, Object> fieldContainer){ |
| this.fieldContainer = fieldContainer; |
| } |
| |
| // @JsonAnySetter |
| public void addField(String name, Object value) { |
| fieldContainer.put(name, value); |
| } |
| |
| public Object getField(String name) { |
| return fieldContainer.get(name); |
| } |
| |
| @Override |
| public Object delField(String fieldName) { |
| return fieldContainer.remove(fieldName); |
| } |
| |
| @JsonIgnore |
| public int getClassVersion() { |
| Object o = fieldContainer.get(CLASSVERSION); |
| return o == null ? 0 : (Integer)o; |
| } |
| |
| public void setClassVersion(int version) { |
| fieldContainer.put(CLASSVERSION, version); |
| } |
| |
| @JsonIgnore |
| public int getOriginalVersion(){ |
| Object o = fieldContainer.get(ORIGINALVERSION); |
| return o == null? -1 : (Integer)o; |
| } |
| public void setOriginalVersion(int version){ |
| fieldContainer.put(ORIGINALVERSION, version); |
| } |
| |
| private void writeObject(ObjectOutputStream oos) throws IOException{ |
| oos.defaultWriteObject(); |
| oos.writeInt(fieldContainer.size()); |
| oos.writeObject(fieldContainer.getClass().getName()); |
| for (String key : fieldContainer.keySet()){ |
| oos.writeObject(key); |
| oos.writeObject(fieldContainer.get(key)); |
| } |
| } |
| private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{ |
| ois.defaultReadObject(); |
| int size = ois.readInt(); |
| String cls = (String)ois.readObject(); |
| try { |
| fieldContainer = (Map<String, Object>)(Class.forName(cls).newInstance()); |
| } catch (Exception e) { |
| //should never get here |
| e.printStackTrace(); |
| } |
| for (int i = 0; i < size; i++){ |
| String key = (String)ois.readObject(); |
| Object value = ois.readObject(); |
| fieldContainer.put(key, value); |
| } |
| } |
| |
| @Override |
| public void upgrade2Newest(){ |
| int version = getClassVersion(); |
| int currentVersion = version; |
| try { |
| currentVersion = (Integer) this.getClass().getField("CURRENT_CLASS_VERSION").get(this); |
| } catch (Exception e) { |
| // should never get here |
| e.printStackTrace(); |
| } |
| if (version == currentVersion) return; |
| if (version > currentVersion){ |
| //should never get here. |
| throw new RuntimeException("class version is newer than newest!"); |
| } |
| setClassVersion(currentVersion); |
| return; |
| } |
| } |