/*
 * This file is part of Nuts Framework.
 * Copyright (C) 2009 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 * 
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.gae.vfs.ngfs;

import nuts.exts.vfs.ndfs.dao.NdfsData;
import nuts.gae.dao.GaeModelMetaData;

import java.util.HashMap;
import java.util.Map;

/**
 */
public class GaeDataMetaData extends GaeModelMetaData<NdfsData> {
	/**
	 * TABLE_NAME = "_nuts_file_data";
	 */
	public static final String TABLE_NAME = "_nuts_vfs_data";

	/*----------------------------------------------------------------------*
	 * PROPERTY NAMES
	 *----------------------------------------------------------------------*/
	/**
	 * PN_ID = "id";
	 */
	public final static String PN_ID = "id";

	/**
	 * PN_FILE_ID = "fileId";
	 */
	public final static String PN_FILE_ID = "fileId";

	/**
	 * PN_ITEM_NO = "itemNo";
	 */
	public final static String PN_ITEM_NO = "itemNo";

	/**
	 * PN_DATA = "data";
	 */
	public final static String PN_DATA = "data";

	/**
	 * PROPERTY_NAMES = { PN_ID, PN_DATA };
	 */
	public final static String[] PROPERTY_NAMES = new String[] { PN_ID, PN_DATA };

	/**
	 * IDENTITY = PN_ID;
	 */
	public final static String IDENTITY = PN_ID;
	
	/*----------------------------------------------------------------------*
	 * PRIMARY KEYS
	 *----------------------------------------------------------------------*/
	/**
	 * PRIMARY_KEYS = { PN_ID };
	 */
	public final static String[] PRIMARY_KEYS = { 
		PN_ID
	};
	
	/*----------------------------------------------------------------------*
	 * CONSTRAINTS
	 *----------------------------------------------------------------------*/
	/**
	 * <PRE>
	 * UNIQUE_KEY_CONSTRAINTS = { { PN_FILE_ID, PN_ITEM_NO } };
	 * </PRE>
	 */
	public final static String[][] UNIQUE_KEY_CONSTRAINTS = { 
		{ PN_FILE_ID, PN_ITEM_NO }
	};
	
	/**
	 * <PRE>
	 * FOREIGN_KEY_CONSTRAINTS = { 
	 * };
	 * </PRE>
	 */
	public final static String[][] FOREIGN_KEY_CONSTRAINTS = { 
	};

	/**
	 * static instance
	 */
	private static final GaeDataMetaData INSTANCE = new GaeDataMetaData();
	
	/**
	 * @return ModelMetaData
	 */
	public static GaeDataMetaData getInstance() {
		return INSTANCE;
	}

	/**
	 * properties
	 */	
	protected Map<String, Object[]> properties;

	/**
	 * Constructor
	 */
	public GaeDataMetaData() {
		properties = new HashMap<String, Object[]>();
		properties.put(PN_ID, new Object[] { 1, Long.class });
		properties.put(PN_FILE_ID, new Object[] { 2, Long.class });
		properties.put(PN_ITEM_NO, new Object[] { 3, Integer.class });
		properties.put(PN_DATA, new Object[] { 4, byte[].class });
	}

	/**
	 * @return the model bean class
	 */
	public Class getModelBeanClass() {
		return NdfsData.class;
	}
	
	/**
	 * @return the model dao class
	 */
	public Class getModelDAOClass() {
		return GaeDataDAO.class;
	}

	/**
	 * @return the model example class
	 */
	public Class getModelExampleClass() {
		return GaeDataExample.class;
	}
	
	/**
	 * @return the table name
	 */
	public String getTableName() {
		return TABLE_NAME;
	}

	/**
	 * @return the table alias
	 */
	public String getTableAlias() {
		return TABLE_NAME;
	}

	/**
	 * @return the property names
	 */
	public String[] getPropertyNames() {
		return PROPERTY_NAMES;
	}

	/**
	 * @return the field names
	 */
	public String[] getFieldNames() {
		return PROPERTY_NAMES;
	}

	/**
	 * @return the identity property name
	 */
	public String getIdentityName() {
		return IDENTITY;
	}
	
	/**
	 * @return the primary key property names
	 */
	public String[] getPrimaryKeys() {
		return PRIMARY_KEYS;
	}

	/**
	 * @return the primary key column names
	 */
	public String[] getPrimaryKeyColumnNames() {
		return PRIMARY_KEYS;
	}
	
	/**
	 * @return the primary key column aliases
	 */
	public String[] getPrimaryKeyColumnAliases() {
		return PRIMARY_KEYS;
	}

	/**
	 * @return the foreign key constraint array
	 */
	public String[][] getForeignKeyConstraints() {
		return FOREIGN_KEY_CONSTRAINTS;
	}

	/**
	 * @param propertyName propertyName
	 * @return true if the property is a primary key
	 */
	public boolean isPrimaryKey(String propertyName) {
		for (String f : PRIMARY_KEYS) {
			if (f.equals(propertyName)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @return the unique key constraints
	 */
	public String[][] getUniqueKeyConstraints() {
		return UNIQUE_KEY_CONSTRAINTS;
	}

	//--------------------------------------------------------------
	// ModelAccessor
	//--------------------------------------------------------------
	/**
	 * create bean object
	 * @return bean instance 
	 */
	public NdfsData createObject() {
		return new NdfsData();
	}

	/**
	 * get read property names
	 * @param data data object (can be null)
	 * @return property names
	 */
	public String[] getReadPropertyNames(NdfsData data) {
		return PROPERTY_NAMES;
	}

	/**
	 * get write property names
	 * @param data data object (can be null)
	 * @return property names
	 */
	public String[] getWritePropertyNames(NdfsData data) {
		return PROPERTY_NAMES;
	}

	/**
	 * get property type
	 * @param propertyName property name
	 * @return property type
	 */
	public Class getPropertyType(String propertyName) {
		return (Class)getPropertyItem(properties, propertyName, 1);
	}

	/**
	 * get property type
	 * @param data data object (can be null)
	 * @param propertyName property name
	 * @return property type
	 */
	public Class getPropertyType(NdfsData data, String propertyName) {
		return (Class)getPropertyItem(properties, propertyName, 1);
	}
	
	/**
	 * get property value 
	 * @param data data object
	 * @param propertyName property name
	 * @return value
	 */
	public Object getPropertyValue(NdfsData data, String propertyName) {
		Integer i = (Integer)getPropertyItem(properties, propertyName, 0);
		if (i == null) {
			throw illegalPropertyException(propertyName);
		}

		switch (i) {
		case 1: return data.getId();
		case 2: return data.getFileId();
		case 3: return data.getItemNo();
		case 4: return data.getData();
		default:
			throw illegalPropertyException(propertyName);
		}
	}
	
	/**
	 * set property value 
	 * @param data data object
	 * @param propertyName property name
	 * @param value value
	 */
	public void setPropertyValue(NdfsData data, String propertyName, Object value) {
		Integer i = (Integer)getPropertyItem(properties, propertyName, 0);
		if (i == null) {
			throw illegalPropertyException(propertyName);
		}

		switch (i) {
		case 1: data.setId((Long)value); return;
		case 2: data.setFileId((Long)value); return;
		case 3: data.setItemNo((Integer)value); return;
		case 4: data.setData((byte[])value); return;
		default:
			throw illegalPropertyException(propertyName);
		}
	}

	/**
	 * set data properties values from map
	 * @param data data
	 * @param map map
	 */
	public void setDataProperties(NdfsData data, Map<String, Object> map) {
		if (map.containsKey(PN_ID)) {
			data.setId((Long)map.get(PN_ID));
		}
		if (map.containsKey(PN_FILE_ID)) {
			data.setFileId((Long)map.get(PN_FILE_ID));
		}
		if (map.containsKey(PN_ITEM_NO)) {
			data.setItemNo((Integer)map.get(PN_ITEM_NO));
		}
		if (map.containsKey(PN_DATA)) {
			data.setData((byte[])map.get(PN_DATA));
		}
	}
	
	/**
	 * get data property values map
	 * @param data data
	 * @return property values map
	 */
	public Map<String, Object> getDataProperties(NdfsData data) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(PN_ID, data.getId());
		map.put(PN_FILE_ID, data.getFileId());
		map.put(PN_ITEM_NO, data.getItemNo());
		map.put(PN_DATA, data.getData());
		return map;
	}
}
