/**
 * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of the Liferay Enterprise
 * Subscription License ("License"). You may not use this file except in
 * compliance with the License. You can obtain a copy of the License by
 * contacting Liferay, Inc. See the License for the specific language governing
 * permissions and limitations under the License, including but not limited to
 * distribution rights of the Software.
 *
 *
 *
 */

package com.liferay.portlet.dynamicdatalists.service.impl;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.language.LanguageUtil;
import com.liferay.portal.kernel.search.Hits;
import com.liferay.portal.kernel.search.Indexable;
import com.liferay.portal.kernel.search.IndexableType;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.search.IndexerRegistryUtil;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.util.ContentTypes;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
import com.liferay.portal.model.User;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portlet.documentlibrary.util.DLUtil;
import com.liferay.portlet.dynamicdatalists.NoSuchRecordVersionException;
import com.liferay.portlet.dynamicdatalists.model.DDLRecord;
import com.liferay.portlet.dynamicdatalists.model.DDLRecordConstants;
import com.liferay.portlet.dynamicdatalists.model.DDLRecordSet;
import com.liferay.portlet.dynamicdatalists.model.DDLRecordVersion;
import com.liferay.portlet.dynamicdatalists.service.base.DDLRecordLocalServiceBaseImpl;
import com.liferay.portlet.dynamicdatalists.util.comparator.DDLRecordVersionVersionComparator;
import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
import com.liferay.portlet.dynamicdatamapping.storage.Field;
import com.liferay.portlet.dynamicdatamapping.storage.Fields;
import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
import com.liferay.portlet.dynamicdatamapping.util.DDMUtil;

import java.io.Serializable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Provides the local service for accessing, adding, deleting, and updating
 * dynamic data list (DDL) records.
 *
 * @author Marcellus Tavares
 * @author Eduardo Lundgren
 */
public class DDLRecordLocalServiceImpl extends DDLRecordLocalServiceBaseImpl {

	@Indexable(type = IndexableType.REINDEX)
	@Override
	public DDLRecord addRecord(
			long userId, long groupId, long recordSetId, int displayIndex,
			Fields fields, ServiceContext serviceContext)
		throws PortalException, SystemException {

		// Record

		User user = userPersistence.findByPrimaryKey(userId);
		Date now = new Date();

		DDLRecordSet recordSet = ddlRecordSetPersistence.findByPrimaryKey(
			recordSetId);

		long recordId = counterLocalService.increment();

		DDLRecord record = ddlRecordPersistence.create(recordId);

		record.setUuid(serviceContext.getUuid());
		record.setGroupId(groupId);
		record.setCompanyId(user.getCompanyId());
		record.setUserId(user.getUserId());
		record.setUserName(user.getFullName());
		record.setVersionUserId(user.getUserId());
		record.setVersionUserName(user.getFullName());
		record.setCreateDate(serviceContext.getCreateDate(now));
		record.setModifiedDate(serviceContext.getModifiedDate(now));

		long ddmStorageId = StorageEngineUtil.create(
			recordSet.getCompanyId(), recordSet.getDDMStructureId(), fields,
			serviceContext);

		record.setDDMStorageId(ddmStorageId);

		record.setRecordSetId(recordSetId);
		record.setVersion(DDLRecordConstants.VERSION_DEFAULT);
		record.setDisplayIndex(displayIndex);

		ddlRecordPersistence.update(record);

		// Record version

		DDLRecordVersion recordVersion = addRecordVersion(
			user, record, ddmStorageId, DDLRecordConstants.VERSION_DEFAULT,
			displayIndex, WorkflowConstants.STATUS_DRAFT);

		// Asset

		Locale locale = serviceContext.getLocale();

		updateAsset(
			userId, record, recordVersion, serviceContext.getAssetCategoryIds(),
			serviceContext.getAssetTagNames(), locale);

		// Workflow

		WorkflowHandlerRegistryUtil.startWorkflowInstance(
			user.getCompanyId(), groupId, userId, DDLRecord.class.getName(),
			recordVersion.getRecordVersionId(), recordVersion, serviceContext);

		return record;
	}

	@Override
	public DDLRecord addRecord(
			long userId, long groupId, long recordSetId, int displayIndex,
			Map<String, Serializable> fieldsMap, ServiceContext serviceContext)
		throws PortalException, SystemException {

		DDLRecordSet recordSet = ddlRecordSetPersistence.findByPrimaryKey(
			recordSetId);

		DDMStructure ddmStructure = recordSet.getDDMStructure();

		Fields fields = toFields(
			ddmStructure.getStructureId(), fieldsMap,
			serviceContext.getLocale(), LocaleUtil.getSiteDefault());

		return ddlRecordLocalService.addRecord(
			userId, groupId, recordSetId, displayIndex, fields, serviceContext);
	}

	@Override
	public void deleteRecord(DDLRecord record)
		throws PortalException, SystemException {

		// Record

		ddlRecordPersistence.remove(record);

		// Record Versions

		List<DDLRecordVersion> recordVersions =
			ddlRecordVersionPersistence.findByRecordId(record.getRecordId());

		for (DDLRecordVersion recordVersion : recordVersions) {
			ddlRecordVersionPersistence.remove(recordVersion);

			// Dynamic data mapping storage

			StorageEngineUtil.deleteByClass(recordVersion.getDDMStorageId());

			// Workflow

			workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
				record.getCompanyId(), record.getGroupId(),
				DDLRecord.class.getName(), recordVersion.getPrimaryKey());
		}

		// Asset

		assetEntryLocalService.deleteEntry(
			DDLRecord.class.getName(), record.getRecordId());

		// Indexer

		Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
			DDLRecord.class);

		indexer.delete(record);
	}

	@Override
	public void deleteRecord(long recordId)
		throws PortalException, SystemException {

		DDLRecord record = ddlRecordPersistence.findByPrimaryKey(recordId);

		deleteRecord(record);
	}

	@Override
	public DDLRecord deleteRecordLocale(
			long recordId, Locale locale, ServiceContext serviceContext)
		throws PortalException, SystemException {

		DDLRecord record = ddlRecordPersistence.findByPrimaryKey(recordId);

		Fields fields = StorageEngineUtil.getFields(record.getDDMStorageId());

		for (Field field : fields) {
			Map<Locale, List<Serializable>> valuesMap = field.getValuesMap();

			valuesMap.remove(locale);
		}

		return ddlRecordLocalService.updateRecord(
			serviceContext.getUserId(), recordId, false,
			DDLRecordConstants.DISPLAY_INDEX_DEFAULT, fields, false,
			serviceContext);
	}

	@Override
	public void deleteRecords(long recordSetId)
		throws PortalException, SystemException {

		List<DDLRecord> records = ddlRecordPersistence.findByRecordSetId(
			recordSetId);

		for (DDLRecord record : records) {
			deleteRecord(record);
		}
	}

	@Override
	public DDLRecord fetchRecord(long recordId) throws SystemException {
		return ddlRecordPersistence.fetchByPrimaryKey(recordId);
	}

	@Override
	public List<DDLRecord> getCompanyRecords(
			long companyId, int status, int scope, int start, int end,
			OrderByComparator orderByComparator)
		throws SystemException {

		return ddlRecordFinder.findByC_S_S(
			companyId, status, scope, start, end, orderByComparator);
	}

	/**
	 * @deprecated As of 6.2.0, replaced by {@link #getCompanyRecords(long, int,
	 *             int, int, int, OrderByComparator)}
	 */
	@Override
	public List<DDLRecord> getCompanyRecords(
			long companyId, int scope, int start, int end,
			OrderByComparator orderByComparator)
		throws SystemException {

		return getCompanyRecords(
			companyId, WorkflowConstants.STATUS_ANY, scope, start, end,
			orderByComparator);
	}

	/**
	 * @deprecated As of 6.2.0, replaced by {@link #getCompanyRecordsCount(long,
	 *             int, int)}
	 */
	@Override
	public int getCompanyRecordsCount(long companyId, int scope)
		throws SystemException {

		return getCompanyRecordsCount(
			companyId, WorkflowConstants.STATUS_ANY, scope);
	}

	@Override
	public int getCompanyRecordsCount(long companyId, int status, int scope)
		throws SystemException {

		return ddlRecordFinder.countByC_S_S(companyId, status, scope);
	}

	@Override
	public DDLRecordVersion getLatestRecordVersion(long recordId)
		throws PortalException, SystemException {

		List<DDLRecordVersion> recordVersions =
			ddlRecordVersionPersistence.findByRecordId(recordId);

		if (recordVersions.isEmpty()) {
			throw new NoSuchRecordVersionException(
				"No record versions found for recordId " + recordId);
		}

		recordVersions = ListUtil.copy(recordVersions);

		Collections.sort(
			recordVersions, new DDLRecordVersionVersionComparator());

		return recordVersions.get(0);
	}

	@Override
	public Long[] getMinAndMaxCompanyRecordIds(
			long companyId, int status, int scope)
		throws SystemException {

		return ddlRecordFinder.findByC_S_S_MinAndMax(companyId, status, scope);
	}

	@Override
	public List<DDLRecord> getMinAndMaxCompanyRecords(
			long companyId, int status, int scope, long minRecordId,
			long maxRecordId)
		throws SystemException {

		return ddlRecordFinder.findByC_S_S_MinAndMax(
			companyId, status, scope, minRecordId, maxRecordId);
	}

	@Override
	public DDLRecord getRecord(long recordId)
		throws PortalException, SystemException {

		return ddlRecordPersistence.findByPrimaryKey(recordId);
	}

	@Override
	public List<DDLRecord> getRecords(long recordSetId) throws SystemException {
		return ddlRecordPersistence.findByRecordSetId(recordSetId);
	}

	@Override
	public List<DDLRecord> getRecords(
			long recordSetId, int status, int start, int end,
			OrderByComparator orderByComparator)
		throws SystemException {

		return ddlRecordFinder.findByR_S(
			recordSetId, status, start, end, orderByComparator);
	}

	@Override
	public List<DDLRecord> getRecords(long recordSetId, long userId)
		throws SystemException {

		return ddlRecordPersistence.findByR_U(recordSetId, userId);
	}

	@Override
	public int getRecordsCount(long recordSetId, int status)
		throws SystemException {

		return ddlRecordFinder.countByR_S(recordSetId, status);
	}

	@Override
	public DDLRecordVersion getRecordVersion(long recordVersionId)
		throws PortalException, SystemException {

		return ddlRecordVersionPersistence.findByPrimaryKey(recordVersionId);
	}

	@Override
	public DDLRecordVersion getRecordVersion(long recordId, String version)
		throws PortalException, SystemException {

		return ddlRecordVersionPersistence.findByR_V(recordId, version);
	}

	@Override
	public List<DDLRecordVersion> getRecordVersions(
			long recordId, int start, int end,
			OrderByComparator orderByComparator)
		throws SystemException {

		return ddlRecordVersionPersistence.findByRecordId(
			recordId, start, end, orderByComparator);
	}

	@Override
	public int getRecordVersionsCount(long recordId) throws SystemException {
		return ddlRecordVersionPersistence.countByRecordId(recordId);
	}

	@Override
	public void revertRecordVersion(
			long userId, long recordId, String version,
			ServiceContext serviceContext)
		throws PortalException, SystemException {

		DDLRecordVersion recordVersion = getRecordVersion(recordId, version);

		if (!recordVersion.isApproved()) {
			return;
		}

		Fields fields = StorageEngineUtil.getFields(
			recordVersion.getDDMStorageId());

		ddlRecordLocalService.updateRecord(
			userId, recordId, true, recordVersion.getDisplayIndex(), fields,
			false, serviceContext);
	}

	@Override
	public Hits search(SearchContext searchContext) throws SystemException {
		try {
			Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
				DDLRecord.class);

			return indexer.search(searchContext);
		}
		catch (Exception e) {
			throw new SystemException(e);
		}
	}

	@Override
	public void updateAsset(
			long userId, DDLRecord record, DDLRecordVersion recordVersion,
			long[] assetCategoryIds, String[] assetTagNames, Locale locale)
		throws PortalException, SystemException {

		boolean addDraftAssetEntry = false;
		boolean visible = true;

		if ((recordVersion != null) && !recordVersion.isApproved()) {
			String version = recordVersion.getVersion();

			if (!version.equals(DDLRecordConstants.VERSION_DEFAULT)) {
				int approvedRecordVersionsCount =
					ddlRecordVersionPersistence.countByR_S(
						record.getRecordId(),
						WorkflowConstants.STATUS_APPROVED);

				if (approvedRecordVersionsCount > 0) {
					addDraftAssetEntry = true;
				}
			}

			visible = false;
		}

		DDLRecordSet recordSet = record.getRecordSet();

		DDMStructure ddmStructure = recordSet.getDDMStructure();

		String ddmStructureName = ddmStructure.getName(locale);

		String recordSetName = recordSet.getName(locale);

		String title = LanguageUtil.format(
			locale, "new-x-for-list-x",
			new Object[] {ddmStructureName, recordSetName}, false);

		if (addDraftAssetEntry) {
			assetEntryLocalService.updateEntry(
				userId, record.getGroupId(), record.getCreateDate(),
				record.getModifiedDate(), DDLRecordConstants.getClassName(),
				recordVersion.getRecordVersionId(), record.getUuid(), 0,
				assetCategoryIds, assetTagNames, false, null, null, null,
				ContentTypes.TEXT_HTML, title, null, StringPool.BLANK, null,
				null, 0, 0, null, false);
		}
		else {
			assetEntryLocalService.updateEntry(
				userId, record.getGroupId(), record.getCreateDate(),
				record.getModifiedDate(), DDLRecordConstants.getClassName(),
				record.getRecordId(), record.getUuid(), 0, assetCategoryIds,
				assetTagNames, visible, null, null, null,
				ContentTypes.TEXT_HTML, title, null, StringPool.BLANK, null,
				null, 0, 0, null, false);
		}
	}

	@Override
	public DDLRecord updateRecord(
			long userId, long recordId, boolean majorVersion, int displayIndex,
			Fields fields, boolean mergeFields, ServiceContext serviceContext)
		throws PortalException, SystemException {

		// Record

		User user = userPersistence.findByPrimaryKey(userId);

		DDLRecord record = ddlRecordPersistence.findByPrimaryKey(recordId);

		record.setModifiedDate(serviceContext.getModifiedDate(null));

		ddlRecordPersistence.update(record);

		// Record version

		DDLRecordVersion recordVersion = record.getLatestRecordVersion();

		if (recordVersion.isApproved()) {
			DDLRecordSet recordSet = record.getRecordSet();

			if (mergeFields) {
				Fields existingFields = StorageEngineUtil.getFields(
					recordVersion.getDDMStorageId());

				fields = DDMUtil.mergeFields(fields, existingFields);
			}

			long ddmStorageId = StorageEngineUtil.create(
				recordSet.getCompanyId(), recordSet.getDDMStructureId(), fields,
				serviceContext);
			String version = getNextVersion(
				recordVersion.getVersion(), majorVersion,
				serviceContext.getWorkflowAction());

			recordVersion = addRecordVersion(
				user, record, ddmStorageId, version, displayIndex,
				WorkflowConstants.STATUS_DRAFT);
		}
		else {
			StorageEngineUtil.update(
				recordVersion.getDDMStorageId(), fields, mergeFields,
				serviceContext);

			String version = recordVersion.getVersion();

			updateRecordVersion(
				user, recordVersion, version, displayIndex,
				recordVersion.getStatus(), serviceContext);
		}

		// Workflow

		WorkflowHandlerRegistryUtil.startWorkflowInstance(
			user.getCompanyId(), record.getGroupId(), userId,
			DDLRecord.class.getName(), recordVersion.getRecordVersionId(),
			recordVersion, serviceContext);

		return record;
	}

	@Override
	public DDLRecord updateRecord(
			long userId, long recordId, int displayIndex,
			Map<String, Serializable> fieldsMap, boolean mergeFields,
			ServiceContext serviceContext)
		throws PortalException, SystemException {

		DDLRecord record = ddlRecordPersistence.findByPrimaryKey(recordId);

		Fields oldFields = record.getFields();

		DDLRecordSet recordSet = record.getRecordSet();

		DDMStructure ddmStructure = recordSet.getDDMStructure();

		Fields fields = toFields(
			ddmStructure.getStructureId(), fieldsMap,
			serviceContext.getLocale(), oldFields.getDefaultLocale());

		return ddlRecordLocalService.updateRecord(
			userId, recordId, false, displayIndex, fields, mergeFields,
			serviceContext);
	}

	@Indexable(type = IndexableType.REINDEX)
	@Override
	public DDLRecord updateStatus(
			long userId, long recordVersionId, int status,
			ServiceContext serviceContext)
		throws PortalException, SystemException {

		// Record version

		User user = userPersistence.findByPrimaryKey(userId);

		DDLRecordVersion recordVersion =
			ddlRecordVersionPersistence.findByPrimaryKey(recordVersionId);

		recordVersion.setStatus(status);
		recordVersion.setStatusByUserId(user.getUserId());
		recordVersion.setStatusByUserName(user.getFullName());
		recordVersion.setStatusDate(new Date());

		ddlRecordVersionPersistence.update(recordVersion);

		// Record

		DDLRecord record = ddlRecordPersistence.findByPrimaryKey(
			recordVersion.getRecordId());

		if (status == WorkflowConstants.STATUS_APPROVED) {
			if (DLUtil.compareVersions(
					record.getVersion(), recordVersion.getVersion()) <= 0) {

				record.setDDMStorageId(recordVersion.getDDMStorageId());
				record.setVersion(recordVersion.getVersion());
				record.setRecordSetId(recordVersion.getRecordSetId());
				record.setDisplayIndex(recordVersion.getDisplayIndex());
				record.setVersion(recordVersion.getVersion());
				record.setVersionUserId(recordVersion.getUserId());
				record.setVersionUserName(recordVersion.getUserName());
				record.setModifiedDate(recordVersion.getCreateDate());

				ddlRecordPersistence.update(record);
			}
		}
		else {
			if (Validator.equals(
					record.getVersion(), recordVersion.getVersion())) {

				String newVersion = DDLRecordConstants.VERSION_DEFAULT;

				List<DDLRecordVersion> approvedRecordVersions =
					ddlRecordVersionPersistence.findByR_S(
						record.getRecordId(),
						WorkflowConstants.STATUS_APPROVED);

				if (!approvedRecordVersions.isEmpty()) {
					newVersion = approvedRecordVersions.get(0).getVersion();
				}

				record.setVersion(newVersion);

				ddlRecordPersistence.update(record);
			}
		}

		return record;
	}

	protected DDLRecordVersion addRecordVersion(
			User user, DDLRecord record, long ddmStorageId, String version,
			int displayIndex, int status)
		throws SystemException {

		long recordVersionId = counterLocalService.increment();

		DDLRecordVersion recordVersion = ddlRecordVersionPersistence.create(
			recordVersionId);

		recordVersion.setGroupId(record.getGroupId());
		recordVersion.setCompanyId(record.getCompanyId());
		recordVersion.setUserId(user.getUserId());
		recordVersion.setUserName(user.getFullName());
		recordVersion.setCreateDate(record.getModifiedDate());
		recordVersion.setDDMStorageId(ddmStorageId);
		recordVersion.setRecordSetId(record.getRecordSetId());
		recordVersion.setRecordId(record.getRecordId());
		recordVersion.setVersion(version);
		recordVersion.setDisplayIndex(displayIndex);
		recordVersion.setStatus(status);
		recordVersion.setStatusByUserId(user.getUserId());
		recordVersion.setStatusByUserName(user.getFullName());
		recordVersion.setStatusDate(record.getModifiedDate());

		ddlRecordVersionPersistence.update(recordVersion);

		return recordVersion;
	}

	protected String getNextVersion(
		String version, boolean majorVersion, int workflowAction) {

		if (workflowAction == WorkflowConstants.ACTION_SAVE_DRAFT) {
			majorVersion = false;
		}

		int[] versionParts = StringUtil.split(version, StringPool.PERIOD, 0);

		if (majorVersion) {
			versionParts[0]++;
			versionParts[1] = 0;
		}
		else {
			versionParts[1]++;
		}

		return versionParts[0] + StringPool.PERIOD + versionParts[1];
	}

	protected Fields toFields(
		long ddmStructureId, Map<String, Serializable> fieldsMap, Locale locale,
		Locale defaultLocale) {

		Fields fields = new Fields();

		for (Map.Entry<String, Serializable> entry : fieldsMap.entrySet()) {
			Field field = new Field();

			field.setDDMStructureId(ddmStructureId);
			field.setName(entry.getKey());

			Serializable value = entry.getValue();

			List<Serializable> serializableValues = _getSerializableValues(
				value);

			if (serializableValues != null) {
				field.addValues(locale, serializableValues);

				if (!locale.equals(defaultLocale)) {
					field.addValues(defaultLocale, serializableValues);
				}
			}
			else {
				field.addValue(locale, String.valueOf(value));

				if (!locale.equals(defaultLocale)) {
					field.addValue(defaultLocale, String.valueOf(value));
				}
			}

			field.setDefaultLocale(defaultLocale);

			fields.put(field);
		}

		Field fieldsDisplayField = fields.get(_FIELDS_DISPLAY_NAME);

		if (fieldsDisplayField == null) {
			StringBundler fieldsDisplayFieldSB = new StringBundler(
				fieldsMap.size() * 4 - 1);

			for (String fieldName : fields.getNames()) {
				fieldsDisplayFieldSB.append(fieldName);
				fieldsDisplayFieldSB.append(_INSTANCE_SEPARATOR);
				fieldsDisplayFieldSB.append(StringUtil.randomString());
				fieldsDisplayFieldSB.append(StringPool.COMMA);
			}

			if (fieldsDisplayFieldSB.index() > 0) {
				fieldsDisplayFieldSB.setIndex(fieldsDisplayFieldSB.index() - 1);
			}

			fieldsDisplayField = new Field(
				ddmStructureId, _FIELDS_DISPLAY_NAME,
				fieldsDisplayFieldSB.toString());

			fields.put(fieldsDisplayField);
		}

		return fields;
	}

	protected void updateRecordVersion(
			User user, DDLRecordVersion recordVersion, String version,
			int displayIndex, int status, ServiceContext serviceContext)
		throws SystemException {

		recordVersion.setUserId(user.getUserId());
		recordVersion.setUserName(user.getFullName());
		recordVersion.setVersion(version);
		recordVersion.setDisplayIndex(displayIndex);
		recordVersion.setStatus(status);
		recordVersion.setStatusByUserId(user.getUserId());
		recordVersion.setStatusByUserName(user.getFullName());
		recordVersion.setStatusDate(serviceContext.getModifiedDate(null));

		ddlRecordVersionPersistence.update(recordVersion);
	}

	private List<Serializable> _getSerializableValues(Serializable value) {
		List<Serializable> serializableValues = null;

		if (value instanceof Collection) {
			Collection<Serializable> values = (Collection<Serializable>)value;

			serializableValues = new ArrayList<Serializable>(values);
		}
		else if (value instanceof Serializable[]) {
			Serializable[] values = (Serializable[])value;

			serializableValues = ListUtil.toList(values);
		}
		else if (value instanceof boolean[]) {
			boolean[] values = (boolean[])value;

			serializableValues = new ArrayList<Serializable>(values.length);

			for (boolean serializableValue : values) {
				serializableValues.add(serializableValue);
			}
		}
		else if (value instanceof double[]) {
			double[] values = (double[])value;

			serializableValues = new ArrayList<Serializable>(values.length);

			for (double serializableValue : values) {
				serializableValues.add(serializableValue);
			}
		}
		else if (value instanceof float[]) {
			float[] values = (float[])value;

			serializableValues = new ArrayList<Serializable>(values.length);

			for (float serializableValue : values) {
				serializableValues.add(serializableValue);
			}
		}
		else if (value instanceof int[]) {
			int[] values = (int[])value;

			serializableValues = new ArrayList<Serializable>(values.length);

			for (int serializableValue : values) {
				serializableValues.add(serializableValue);
			}
		}
		else if (value instanceof long[]) {
			long[] values = (long[])value;

			serializableValues = new ArrayList<Serializable>(values.length);

			for (long serializableValue : values) {
				serializableValues.add(serializableValue);
			}
		}
		else if (value instanceof short[]) {
			short[] values = (short[])value;

			serializableValues = new ArrayList<Serializable>(values.length);

			for (short serializableValue : values) {
				serializableValues.add(serializableValue);
			}
		}

		return serializableValues;
	}

	private static final String _FIELDS_DISPLAY_NAME = "_fieldsDisplay";

	private static final String _INSTANCE_SEPARATOR = "_INSTANCE_";

}