blob: 2efcf27efefe20910badaa6bd658e8b9b95426f3 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.gora.persistency.ws.impl;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import org.apache.gora.persistency.Persistent;
import org.apache.gora.persistency.StateManager;
/**
* Base classs implementing common functionality for Web services
* backed persistent classes.
*/
public abstract class PersistentWSBase implements Persistent {
/**
* Maps keys to their own classes
*/
protected static Map<Class<?>, Map<String, Integer>> FIELD_MAP =
new HashMap<Class<?>, Map<String,Integer>>();
/**
* Maps fields to their own classes
*/
protected static Map<Class<?>, String[]> FIELDS =
new HashMap<Class<?>, String[]>();
/**
* Object used to manage the state of fields
*/
private StateManager stateManager;
/**
* Constructor
*/
protected PersistentWSBase() {
this(new StateManagerWSImpl());
}
/**
* Constructor using a stateManager object
* @param stateManager
*/
protected PersistentWSBase(StateManager stateManager) {
this.stateManager = stateManager;
stateManager.setManagedPersistent(this);
}
/** Subclasses should call this function for all the persistable fields
* in the class to register them.
* @param clazz the Persistent class
* @param fields the name of the fields of the class
*/
protected static void registerFields(Class<?> clazz, String... fields) {
FIELDS.put(clazz, fields);
int fieldsLength = fields == null ? 0 :fields.length;
HashMap<String, Integer> map = new HashMap<String, Integer>(fieldsLength);
for(int i=0; i < fieldsLength; i++) {
map.put(fields[i], i);
}
FIELD_MAP.put(clazz, map);
}
@Override
/**
* Gets the state manager
*/
public StateManager getStateManager() {
return stateManager;
}
@Override
/**
* Gets fields using a specific class
*/
public String[] getFields() {
return FIELDS.get(getClass());
}
@Override
/**
* Gets a specific field from the fields map
*/
public String getField(int index) {
return FIELDS.get(getClass())[index];
}
@Override
/**
* Gets a field index based on the field name
*/
public int getFieldIndex(String field) {
return FIELD_MAP.get(getClass()).get(field);
}
@Override
/**
* Clears maps of fields
*/
public void clear() {
// TODO study the specific cases for other datatypes
clearDirty();
clearReadable();
}
@Override
/**
* Determines if a class is new or not
*/
public boolean isNew() {
return getStateManager().isNew(this);
}
@Override
/**
* Sets this element as a new one inside the stateManager object
*/
public void setNew() {
getStateManager().setNew(this);
}
@Override
/**
* Clears a new object from the stateManager
*/
public void clearNew() {
getStateManager().clearNew(this);
}
@Override
/**
* Determines if an object has been modified or not
*/
public boolean isDirty() {
return getStateManager().isDirty(this);
}
@Override
/**
* Determines if an object has been modified or not
* based on its field index
*/
public boolean isDirty(int fieldIndex) {
return getStateManager().isDirty(this, fieldIndex);
}
@Override
/**
* Determines if an object has been modified or not
* based on its field name
*/
public boolean isDirty(String field) {
return isDirty(getFieldIndex(field));
}
@Override
/**
* Sets this class as dirty
*/
public void setDirty() {
getStateManager().setDirty(this);
}
@Override
/**
* Sets a specific field as dirty using its index
*/
public void setDirty(int fieldIndex) {
getStateManager().setDirty(this, fieldIndex);
}
@Override
/**
* Sets a specific field as dirty using its name
*/
public void setDirty(String field) {
setDirty(getFieldIndex(field));
}
@Override
/**
* Clears dirty fields using its index
*/
public void clearDirty(int fieldIndex) {
getStateManager().clearDirty(this, fieldIndex);
}
@Override
/**
* Clears dirty fields using its name
*/
public void clearDirty(String field) {
clearDirty(getFieldIndex(field));
}
@Override
/**
* Clears dirty fields from the state manager
*/
public void clearDirty() {
getStateManager().clearDirty(this);
}
@Override
/**
* Checks if a field is readable using its index
*/
public boolean isReadable(int fieldIndex) {
return getStateManager().isReadable(this, fieldIndex);
}
@Override
/**
* Checks if a field is readable using its name
*/
public boolean isReadable(String field) {
return isReadable(getFieldIndex(field));
}
@Override
/**
* Sets a field as readable using its index
*/
public void setReadable(int fieldIndex) {
getStateManager().setReadable(this, fieldIndex);
}
@Override
/**
* Sets a field as readable using its name
*/
public void setReadable(String field) {
setReadable(getFieldIndex(field));
}
@Override
/**
* Clears this readable object from the state manager
*/
public void clearReadable() {
getStateManager().clearReadable(this);
}
@Override
/**
* Clears a readable object based on its field index
* using a stateManager object
*/
public void clearReadable(int fieldIndex) {
getStateManager().clearReadable(this, fieldIndex);
}
@Override
/**
* Clears a readable object based on its field name
* using a stateManager object
*/
public void clearReadable(String field) {
clearReadable(getFieldIndex(field));
}
@Override
/**
* Determines if an object is equal to this class
*/
public boolean equals(Object o) {
if (this == o) return true;
// TODO we should check if the object has schema or not
return true;
}
@Override
// TODO
public int hashCode() {
int result = 1;
return result;
}
/** ByteBuffer.hashCode() takes into account the position of the
* buffer, but we do not want that*/
private int getByteBufferHashCode(ByteBuffer buf) {
int h = 1;
int p = buf.arrayOffset();
for (int j = buf.limit() - 1; j >= p; j--)
h = 31 * h + buf.get(j);
return h;
}
@Override
/**
* Clones a persistent object
*/
public Persistent clone() {
return null;
}
@Override
/**
* Converts an object to string
*/
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(super.toString());
builder.append(" {\n");
// TODO get fields
builder.append("}");
return builder.toString();
}
/**
* Checks if a field is equal between two objects
* @param index
* @param value
* @return
*/
protected boolean isFieldEqual(int index, Object value) {
// TODO
return true;
}
}