/*
 * 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.NdfsFile;
import nuts.gae.dao.GaeModelMetaData;

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

/**
 * GaeFileMetaData
 */
public class GaeFileMetaData extends GaeModelMetaData<NdfsFile> {
	/**
	 * TABLE_NAME = "_nuts_file";
	 */
	public static final String TABLE_NAME = "_nuts_vfs_file";

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

	/**
	 * PN_PARENT_ID = "parentId";
	 */
	public final static String PN_PARENT_ID = "parentId";

	/**
	 * PN_NAME = "name";
	 */
	public final static String PN_NAME = "name";

	/**
	 * PN_FOLDER = "folder";
	 */
	public final static String PN_FOLDER = "folder";

	/**
	 * PN_LENGTH = "length";
	 */
	public final static String PN_LENGTH = "length";

	/**
	 * PN_LAST_MODIFIED = "lastModified";
	 */
	public final static String PN_LAST_MODIFIED = "lastModified";

	/**
	 * PN_HIDDEN = "hidden";
	 */
	public final static String PN_HIDDEN = "hidden";;

	/**
	 * PN_READABLE = "readable";
	 */
	public final static String PN_READABLE = "readable";

	/**
	 * PN_WRITEABLE = "writeable";
	 */
	public final static String PN_WRITEABLE = "writeable";

	/**
	 * PROPERTY_NAMES = { PN_ID, PN_PARENT_ID, PN_NAME, PN_FOLDER, PN_LENGTH, PN_LAST_MODIFIED, PN_HIDDEN, PN_READABLE, PN_WRITEABLE };
	 */
	public final static String[] PROPERTY_NAMES = new String[] { PN_ID, PN_PARENT_ID, PN_NAME, PN_FOLDER, PN_LENGTH, PN_LAST_MODIFIED, PN_HIDDEN, PN_READABLE, PN_WRITEABLE };

	/**
	 * 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_PARENT_ID, PN_NAME }
	 * };
	 * </PRE>
	 */
	public final static String[][] UNIQUE_KEY_CONSTRAINTS = { 
		{ PN_PARENT_ID, PN_NAME }
	};
	
	/**
	 * <PRE>
	 * FOREIGN_KEY_CONSTRAINTS = { 
	 * };
	 * </PRE>
	 */
	public final static String[][] FOREIGN_KEY_CONSTRAINTS = { 
	};

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

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

	/**
	 * Constructor
	 */
	public GaeFileMetaData() {
		properties = new HashMap<String, Object[]>();
		properties.put(PN_ID, new Object[] { 1, Long.class });
		properties.put(PN_PARENT_ID, new Object[] { 2, Long.class });
		properties.put(PN_NAME, new Object[] { 3, String.class });
		properties.put(PN_FOLDER, new Object[] { 4, Boolean.class });
		properties.put(PN_LENGTH, new Object[] { 5, Long.class });
		properties.put(PN_LAST_MODIFIED, new Object[] { 6, Date.class });
		properties.put(PN_HIDDEN, new Object[] { 7, Boolean.class });
		properties.put(PN_READABLE, new Object[] { 8, Boolean.class });
		properties.put(PN_WRITEABLE, new Object[] { 9, Boolean.class });
	}

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

	/**
	 * @return the model example class
	 */
	public Class getModelExampleClass() {
		return GaeFileExample.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 NdfsFile createObject() {
		return new NdfsFile();
	}

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

	/**
	 * get write property names
	 * @param data data object (can be null)
	 * @return property names
	 */
	public String[] getWritePropertyNames(NdfsFile 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(NdfsFile 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(NdfsFile 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.getParentId();
		case 3: return data.getName();
		case 4: return data.getFolder();
		case 5: return data.getLength();
		case 6: return data.getLastModified();
		case 7: return data.getHidden();
		case 8: return data.getReadable();
		case 9: return data.getWriteable();
		default: 
			throw illegalPropertyException(propertyName);
		}
	}
	
	/**
	 * set property value 
	 * @param data data object
	 * @param propertyName property name
	 * @param value value
	 */
	public void setPropertyValue(NdfsFile 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.setParentId((Long)value); return;
		case 3: data.setName((String)value); return;
		case 4: data.setFolder((Boolean)value); return;
		case 5: data.setLength((Long)value); return;
		case 6: data.setLastModified((Date)value); return;
		case 7: data.setHidden((Boolean)value); return;
		case 8: data.setReadable((Boolean)value); return;
		case 9: data.setWriteable((Boolean)value); return;
		default:
			throw illegalPropertyException(propertyName);
		}
	}

	/**
	 * set data properties values from map
	 * @param data data
	 * @param map map
	 */
	public void setDataProperties(NdfsFile data, Map<String, Object> map) {
		if (map.containsKey(PN_ID)) {
			data.setId((Long)map.get(PN_ID));
		}
		if (map.containsKey(PN_PARENT_ID)) {
			data.setParentId((Long)map.get(PN_PARENT_ID));
		}
		if (map.containsKey(PN_NAME)) {
			data.setName((String)map.get(PN_NAME));
		}
		if (map.containsKey(PN_FOLDER)) {
			data.setFolder((Boolean)map.get(PN_FOLDER));
		}
		if (map.containsKey(PN_LENGTH)) {
			data.setLength((Long)map.get(PN_LENGTH));
		}
		if (map.containsKey(PN_LAST_MODIFIED)) {
			data.setLastModified((Date)map.get(PN_LAST_MODIFIED));
		}
		if (map.containsKey(PN_HIDDEN)) {
			data.setHidden((Boolean)map.get(PN_HIDDEN));
		}
		if (map.containsKey(PN_READABLE)) {
			data.setReadable((Boolean)map.get(PN_READABLE));
		}
		if (map.containsKey(PN_WRITEABLE)) {
			data.setWriteable((Boolean)map.get(PN_WRITEABLE));
		}
	}
	
	/**
	 * get data property values map
	 * @param data data
	 * @return property values map
	 */
	public Map<String, Object> getDataProperties(NdfsFile data) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(PN_ID, data.getId());
		map.put(PN_PARENT_ID, data.getParentId());
		map.put(PN_NAME, data.getName());
		map.put(PN_FOLDER, data.getFolder());
		map.put(PN_LENGTH, data.getLength());
		map.put(PN_LAST_MODIFIED, data.getLastModified());
		map.put(PN_HIDDEN, data.getHidden());
		map.put(PN_READABLE, data.getReadable());
		map.put(PN_WRITEABLE, data.getWriteable());
		return map;
	}
}
