/** * Copyright (c) 2006-2011 Floggy Open Source Group. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sourceforge.floggy.persistence.impl.migration; import java.io.DataInputStream; import java.util.Calendar; import java.util.Date; import java.util.Hashtable; import java.util.Stack; import java.util.TimeZone; import java.util.Vector; import javax.microedition.rms.RecordEnumeration; import javax.microedition.rms.RecordStore; import javax.microedition.rms.RecordStoreException; import net.sourceforge.floggy.persistence.FloggyException; import net.sourceforge.floggy.persistence.Persistable; import net.sourceforge.floggy.persistence.PersistableManager; import net.sourceforge.floggy.persistence.impl.PersistableMetadata; import net.sourceforge.floggy.persistence.impl.PersistableMetadataManager; import net.sourceforge.floggy.persistence.impl.RecordStoreManager; import net.sourceforge.floggy.persistence.impl.SerializationManager; import net.sourceforge.floggy.persistence.impl.Utils; import net.sourceforge.floggy.persistence.impl.__Persistable; import net.sourceforge.floggy.persistence.migration.Enumeration; import net.sourceforge.floggy.persistence.migration.FieldPersistableInfo; /** * DOCUMENT ME! * * @author <a href="mailto:thiago.moreira@floggy.org">Thiago Moreira</a> * @version $Revision$ */ public abstract class AbstractEnumerationImpl implements Enumeration { /** * DOCUMENT ME! */ protected PersistableManager manager = PersistableManager.getInstance(); /** * DOCUMENT ME! */ protected PersistableMetadata classBasedMetadata; /** * DOCUMENT ME! */ protected PersistableMetadata rmsBasedMetadata; /** * DOCUMENT ME! */ protected RecordEnumeration enumeration; /** * DOCUMENT ME! */ protected RecordStore recordStore; /** * DOCUMENT ME! */ protected boolean iterationMode; /** * DOCUMENT ME! */ protected boolean lazy; /** * DOCUMENT ME! */ protected int recordId = -1; /** * Creates a new AbstractEnumerationImpl object. * * @param rmsBasedMetadata DOCUMENT ME! * @param classBasedMetadata DOCUMENT ME! * @param enumeration DOCUMENT ME! * @param recordStore DOCUMENT ME! * @param lazy DOCUMENT ME! * @param iterationMode DOCUMENT ME! * * @throws RecordStoreException DOCUMENT ME! */ protected AbstractEnumerationImpl(PersistableMetadata rmsBasedMetadata, PersistableMetadata classBasedMetadata, RecordEnumeration enumeration, RecordStore recordStore, boolean lazy, boolean iterationMode) throws RecordStoreException { this.rmsBasedMetadata = rmsBasedMetadata; this.classBasedMetadata = classBasedMetadata; this.enumeration = enumeration; this.recordStore = recordStore; this.lazy = lazy; this.iterationMode = iterationMode; } /** * DOCUMENT ME! * * @return DOCUMENT ME! * * @throws FloggyException DOCUMENT ME! */ public int delete() throws FloggyException { if (recordId != -1) { try { recordStore.deleteRecord(recordId); int temp = recordId; recordId = -1; return temp; } catch (RecordStoreException ex) { throw Utils.handleException(ex); } } throw new FloggyException( "There isn't a register to delete. You have to iterate over the enumeration before call delete."); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public int getSize() { return enumeration.numRecords(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean hasMoreElements() { return enumeration.hasNextElement(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! * * @throws FloggyException DOCUMENT ME! */ public Hashtable nextElement() throws FloggyException { if ((recordId != -1) && !iterationMode) { throw new FloggyException( "You should delete or update the current register before step into the next one."); } Hashtable hashtable = new HashtableValueNullable(); try { recordId = enumeration.nextRecordId(); byte[] data = recordStore.getRecord(recordId); buildPersistable(rmsBasedMetadata, data, hashtable); } catch (Exception ex) { throw Utils.handleException(ex); } return hashtable; } /** * DOCUMENT ME! * * @param persistable DOCUMENT ME! * * @return DOCUMENT ME! * * @throws FloggyException DOCUMENT ME! */ public int update(Persistable persistable) throws FloggyException { if (recordId != -1) { __Persistable __persistable = Utils.checkArgumentAndCast(persistable); __persistable.__setId(recordId); int temp = manager.save(__persistable); recordId = -1; return temp; } throw new FloggyException( "There isn't a register to update. You have to iterate over the enumeration before call update."); } /** * DOCUMENT ME! * * @param rmsBasedMetadata DOCUMENT ME! * @param data DOCUMENT ME! * @param hashtable DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected abstract void buildPersistable( PersistableMetadata rmsBasedMetadata, byte[] data, Hashtable hashtable) throws Exception; /** * DOCUMENT ME! * * @param type DOCUMENT ME! * @param size DOCUMENT ME! * * @return DOCUMENT ME! * * @throws FloggyException DOCUMENT ME! */ protected Object[] createArray(int type, int size) throws FloggyException { switch (type) { case PersistableMetadata.BOOLEAN: return new Boolean[size]; case PersistableMetadata.BYTE: return new Byte[size]; case PersistableMetadata.CALENDAR: return new Calendar[size]; case PersistableMetadata.CHARACTER: return new Character[size]; case PersistableMetadata.DATE: return new Date[size]; case PersistableMetadata.DOUBLE: return new Double[size]; case PersistableMetadata.FLOAT: return new Float[size]; case PersistableMetadata.HASHTABLE: return new Hashtable[size]; case PersistableMetadata.INT: return new Integer[size]; case PersistableMetadata.LONG: return new Long[size]; case PersistableMetadata.PERSISTABLE: return new FieldPersistableInfo[size]; case PersistableMetadata.SHORT: return new Short[size]; case PersistableMetadata.STACK: return new Stack[size]; case PersistableMetadata.STRING: return new String[size]; case PersistableMetadata.STRINGBUFFER: return new StringBuffer[size]; case PersistableMetadata.TIMEZONE: return new TimeZone[size]; case PersistableMetadata.VECTOR: return new Vector[size]; default: throw new FloggyException("Type Unknow: " + type); } } /** * DOCUMENT ME! * * @param type DOCUMENT ME! * @param size DOCUMENT ME! * * @return DOCUMENT ME! * * @throws FloggyException DOCUMENT ME! */ protected Object[] createArrayCLDC10(int type, int size) throws FloggyException { switch (type) { case PersistableMetadata.BOOLEAN: return new Boolean[size]; case PersistableMetadata.BYTE: return new Byte[size]; case PersistableMetadata.CALENDAR: return new Calendar[size]; case PersistableMetadata.CHARACTER: return new Character[size]; case PersistableMetadata.DATE: return new Date[size]; case PersistableMetadata.HASHTABLE: return new Hashtable[size]; case PersistableMetadata.INT: return new Integer[size]; case PersistableMetadata.LONG: return new Long[size]; case PersistableMetadata.PERSISTABLE: return new FieldPersistableInfo[size]; case PersistableMetadata.SHORT: return new Short[size]; case PersistableMetadata.STACK: return new Stack[size]; case PersistableMetadata.STRING: return new String[size]; case PersistableMetadata.STRINGBUFFER: return new StringBuffer[size]; case PersistableMetadata.TIMEZONE: return new TimeZone[size]; case PersistableMetadata.VECTOR: return new Vector[size]; default: throw new FloggyException("Type Unknow: " + type); } } /** * DOCUMENT ME! * * @param type DOCUMENT ME! * @param fieldName DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected Object readArray(int type, String fieldName, DataInputStream dis) throws Exception { Object object = null; if (dis.readByte() == SerializationManager.NOT_NULL) { int size = dis.readInt(); if ((type & PersistableMetadata.PRIMITIVE) == PersistableMetadata.PRIMITIVE) { type = type & ~PersistableMetadata.PRIMITIVE; switch (type) { case PersistableMetadata.BOOLEAN: object = readBooleanArray(size, dis); break; case PersistableMetadata.BYTE: object = readByteArray(size, dis); break; case PersistableMetadata.CHARACTER: object = readCharArray(size, dis); break; case PersistableMetadata.DOUBLE: object = readDoubleArray(size, dis); break; case PersistableMetadata.FLOAT: object = readFloatArray(size, dis); break; case PersistableMetadata.INT: object = readIntArray(size, dis); break; case PersistableMetadata.LONG: object = readLongArray(size, dis); break; case PersistableMetadata.SHORT: object = readShortArray(size, dis); break; } } else { Object[] array = createArray(type, size); for (int i = 0; i < size; i++) { array[i] = readObject(type, fieldName, dis); } object = array; } } return object; } /** * DOCUMENT ME! * * @param type DOCUMENT ME! * @param fieldName DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected Object readArrayCLDC10(int type, String fieldName, DataInputStream dis) throws Exception { Object object = null; if (dis.readByte() == SerializationManager.NOT_NULL) { int size = dis.readInt(); if ((type & PersistableMetadata.PRIMITIVE) == PersistableMetadata.PRIMITIVE) { type = type & ~PersistableMetadata.PRIMITIVE; switch (type) { case PersistableMetadata.BOOLEAN: object = readBooleanArray(size, dis); break; case PersistableMetadata.BYTE: object = readByteArray(size, dis); break; case PersistableMetadata.CHARACTER: object = readCharArray(size, dis); break; case PersistableMetadata.INT: object = readIntArray(size, dis); break; case PersistableMetadata.LONG: object = readLongArray(size, dis); break; case PersistableMetadata.SHORT: object = readShortArray(size, dis); break; } } else { Object[] array = createArray(type, size); for (int i = 0; i < size; i++) { array[i] = readObject(type, fieldName, dis); } object = array; } } return object; } /** * DOCUMENT ME! * * @param size DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected boolean[] readBooleanArray(int size, DataInputStream dis) throws Exception { boolean[] temp = new boolean[size]; for (int i = 0; i < temp.length; i++) { temp[i] = dis.readBoolean(); } return temp; } /** * DOCUMENT ME! * * @param size DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected byte[] readByteArray(int size, DataInputStream dis) throws Exception { byte[] temp = new byte[size]; for (int i = 0; i < temp.length; i++) { temp[i] = dis.readByte(); } return temp; } /** * DOCUMENT ME! * * @param size DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected char[] readCharArray(int size, DataInputStream dis) throws Exception { char[] temp = new char[size]; for (int i = 0; i < temp.length; i++) { temp[i] = dis.readChar(); } return temp; } /** * DOCUMENT ME! * * @param size DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected double[] readDoubleArray(int size, DataInputStream dis) throws Exception { double[] temp = new double[size]; for (int i = 0; i < temp.length; i++) { temp[i] = dis.readDouble(); } return temp; } /** * DOCUMENT ME! * * @param size DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected float[] readFloatArray(int size, DataInputStream dis) throws Exception { float[] temp = new float[size]; for (int i = 0; i < temp.length; i++) { temp[i] = dis.readFloat(); } return temp; } /** * DOCUMENT ME! * * @param size DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected int[] readIntArray(int size, DataInputStream dis) throws Exception { int[] temp = new int[size]; for (int i = 0; i < temp.length; i++) { temp[i] = dis.readInt(); } return temp; } /** * DOCUMENT ME! * * @param size DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected long[] readLongArray(int size, DataInputStream dis) throws Exception { long[] temp = new long[size]; for (int i = 0; i < temp.length; i++) { temp[i] = dis.readLong(); } return temp; } /** * DOCUMENT ME! * * @param type DOCUMENT ME! * @param fieldName DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! * @throws FloggyException DOCUMENT ME! */ protected Object readObject(int type, String fieldName, DataInputStream dis) throws Exception { switch (type) { case PersistableMetadata.BOOLEAN: return SerializationManager.readBoolean(dis); case PersistableMetadata.BYTE: return SerializationManager.readByte(dis); case PersistableMetadata.CALENDAR: return SerializationManager.readCalendar(dis); case PersistableMetadata.CHARACTER: return SerializationManager.readChar(dis); case PersistableMetadata.DATE: return SerializationManager.readDate(dis); case PersistableMetadata.DOUBLE: return SerializationManager.readDouble(dis); case PersistableMetadata.FLOAT: return SerializationManager.readFloat(dis); case PersistableMetadata.HASHTABLE: return SerializationManager.readHashtable(dis); case PersistableMetadata.INT: return SerializationManager.readInt(dis); case PersistableMetadata.LONG: return SerializationManager.readLong(dis); case PersistableMetadata.PERSISTABLE: { FieldPersistableInfo fpi = null; String fieldClassName = rmsBasedMetadata.getPersistableImplementationClassForField(fieldName); switch (dis.readByte()) { case -1: fieldClassName = dis.readUTF(); case SerializationManager.NOT_NULL: int fieldId = dis.readInt(); fpi = new FieldPersistableInfo(fieldId, fieldClassName); break; } return fpi; } case PersistableMetadata.SHORT: return SerializationManager.readShort(dis); case PersistableMetadata.STACK: return SerializationManager.readStack(dis, lazy); case PersistableMetadata.STRING: return SerializationManager.readString(dis); case PersistableMetadata.STRINGBUFFER: return SerializationManager.readStringBuffer(dis); case PersistableMetadata.TIMEZONE: return SerializationManager.readTimeZone(dis); case PersistableMetadata.VECTOR: return SerializationManager.readVector(dis, lazy); default: throw new FloggyException("Type Unknow: " + type); } } /** * DOCUMENT ME! * * @param type DOCUMENT ME! * @param fieldName DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! * @throws FloggyException DOCUMENT ME! */ protected Object readObjectCLDC10(int type, String fieldName, DataInputStream dis) throws Exception { switch (type) { case PersistableMetadata.BOOLEAN: return SerializationManager.readBoolean(dis); case PersistableMetadata.BYTE: return SerializationManager.readByte(dis); case PersistableMetadata.CALENDAR: return SerializationManager.readCalendar(dis); case PersistableMetadata.CHARACTER: return SerializationManager.readChar(dis); case PersistableMetadata.DATE: return SerializationManager.readDate(dis); case PersistableMetadata.HASHTABLE: return SerializationManager.readHashtable(dis); case PersistableMetadata.INT: return SerializationManager.readInt(dis); case PersistableMetadata.LONG: return SerializationManager.readLong(dis); case PersistableMetadata.PERSISTABLE: { FieldPersistableInfo fpi = null; String fieldClassName = rmsBasedMetadata.getPersistableImplementationClassForField(fieldName); switch (dis.readByte()) { case -1: fieldClassName = dis.readUTF(); case SerializationManager.NOT_NULL: int fieldId = dis.readInt(); fpi = new FieldPersistableInfo(fieldId, fieldClassName); break; } return fpi; } case PersistableMetadata.SHORT: return SerializationManager.readShort(dis); case PersistableMetadata.STACK: return SerializationManager.readStack(dis, lazy); case PersistableMetadata.STRING: return SerializationManager.readString(dis); case PersistableMetadata.STRINGBUFFER: return SerializationManager.readStringBuffer(dis); case PersistableMetadata.TIMEZONE: return SerializationManager.readTimeZone(dis); case PersistableMetadata.VECTOR: return SerializationManager.readVector(dis, lazy); default: throw new FloggyException("Type Unknow: " + type); } } /** * DOCUMENT ME! * * @param type DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! * @throws FloggyException DOCUMENT ME! */ protected Object readPrimitive(int type, DataInputStream dis) throws Exception { switch (type) { case PersistableMetadata.BOOLEAN: return dis.readBoolean() ? Utils.TRUE : Utils.FALSE; case PersistableMetadata.BYTE: return new Byte(dis.readByte()); case PersistableMetadata.CHARACTER: return new Character(dis.readChar()); case PersistableMetadata.DOUBLE: return new Double(dis.readDouble()); case PersistableMetadata.FLOAT: return new Float(dis.readFloat()); case PersistableMetadata.INT: return new Integer(dis.readInt()); case PersistableMetadata.LONG: return new Long(dis.readLong()); case PersistableMetadata.SHORT: return new Short(dis.readShort()); default: throw new FloggyException("Type Unknow: " + type); } } /** * DOCUMENT ME! * * @param type DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! * @throws FloggyException DOCUMENT ME! */ protected Object readPrimitiveCLDC10(int type, DataInputStream dis) throws Exception { switch (type) { case PersistableMetadata.BOOLEAN: return dis.readBoolean() ? Utils.TRUE : Utils.FALSE; case PersistableMetadata.BYTE: return new Byte(dis.readByte()); case PersistableMetadata.CHARACTER: return new Character(dis.readChar()); case PersistableMetadata.INT: return new Integer(dis.readInt()); case PersistableMetadata.LONG: return new Long(dis.readLong()); case PersistableMetadata.SHORT: return new Short(dis.readShort()); default: throw new FloggyException("Type Unknow: " + type); } } /** * DOCUMENT ME! * * @param size DOCUMENT ME! * @param dis DOCUMENT ME! * * @return DOCUMENT ME! * * @throws Exception DOCUMENT ME! */ protected short[] readShortArray(int size, DataInputStream dis) throws Exception { short[] temp = new short[size]; for (int i = 0; i < temp.length; i++) { temp[i] = dis.readShort(); } return temp; } /** * DOCUMENT ME! * * @throws FloggyException DOCUMENT ME! */ void finish() throws FloggyException { if (!enumeration.hasNextElement()) { enumeration.destroy(); RecordStoreManager.closeRecordStore(recordStore); if (rmsBasedMetadata != classBasedMetadata) { try { classBasedMetadata.setRecordId(rmsBasedMetadata.getRecordId()); classBasedMetadata.setRecordStoreVersion(PersistableMetadataManager .getBytecodeVersion()); PersistableMetadataManager.saveRMSStructure(classBasedMetadata); } catch (Exception ex) { throw Utils.handleException(ex); } } } else { throw new FloggyException( "The enumeration must be whole processed before finish the process!"); } } }