All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.store.storage.restadapter.types.ValueReader Maven / Gradle / Ivy

package org.eclipse.store.storage.restadapter.types;

/*-
 * #%L
 * EclipseStore Storage REST Adapter
 * %%
 * Copyright (C) 2023 MicroStream Software
 * %%
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 * 
 * SPDX-License-Identifier: EPL-2.0
 * #L%
 */

import java.util.ArrayList;
import java.util.List;

import org.eclipse.serializer.collections.types.XGettingSequence;
import org.eclipse.serializer.meta.NotImplementedYetError;
import org.eclipse.serializer.persistence.binary.types.Binary;
import org.eclipse.serializer.persistence.types.PersistenceTypeDefinition;
import org.eclipse.serializer.persistence.types.PersistenceTypeDefinitionMember;
import org.eclipse.serializer.persistence.types.PersistenceTypeDescriptionMemberFieldGeneric;
import org.eclipse.serializer.persistence.types.PersistenceTypeDescriptionMemberFieldGenericComplex;
import org.eclipse.serializer.persistence.types.PersistenceTypeDictionary;

public interface ValueReader
{
	///////////////////////////////////////////////////////////////////////////
	// interface methods //
	////////////

	public Object readValue(Binary binary, long offset);
	public long getBinarySize(final Binary binary, final long offset);

	public default long getVariableLength(final Binary binary, final long offset)
	{
		return -1;
	}


	///////////////////////////////////////////////////////////////////////////
	// static methods //
	///////////////////

	public static ValueReader[] deriveValueReaders(final PersistenceTypeDefinition td)
	{
		final XGettingSequence members = td.instanceMembers();
		final ValueReader[] valueReaders = new ValueReader[members.intSize()];

		int i = 0;
		for(final PersistenceTypeDefinitionMember member : td.instanceMembers())
		{
			valueReaders[i++] = deriveValueReader(member);
		}

		return valueReaders;
	}

	public static ValueReader deriveValueReader(final PersistenceTypeDefinitionMember member)
	{
		/*
		 * select from a variety of stateless ValueReader implementations:
		 * - wrap a primitive value in an instance of its respective Wrapper type
		 * - wrap a reference in a generic "Reference" type holding the objectId (for displaying later)
		 * - wrap a "[char]" member's data in a String
		 * - wrap a "[list]" member's data in a primitive array if there's only a single primitive nested member
		 * - wrap a "[list]" member's data in an Object[] if there's only a single non-primitive nested member
		 * - wrap a "[list]" member's data in an Object[][] if there's more than one nested member.
		 *
		 * Note that non-referential native types (primitive wrappers, String, Date, primitive arrays, etc.) should
		 * be handled by their TypeHandler directly instead of analyzed generically.
		 */

		if(member.isPrimitive())
		{
			return new ValueReaderPrimitive(member);
		}

		if(member.isReference())
		{
			return new ValueReaderReference();
		}

		if(member.isVariableLength())
		{
			return deriveVariableLengthValueReader(member);
		}

		throw new NotImplementedYetError();
	}

	public static ValueReader deriveVariableLengthValueReader(final PersistenceTypeDefinitionMember member)
	{

		if(member.typeName().contentEquals(PersistenceTypeDictionary.Symbols.typeChars()))
		{
			return new ValueReaderPrimitiveCharList(member);
		}

		if(member.typeName().contentEquals(PersistenceTypeDictionary.Symbols.typeBytes()))
		{
			return new ValueReaderPrimitiveByteList(member);
		}

		if(member.typeName().contentEquals(PersistenceTypeDictionary.Symbols.typeComplex()))
		{
			return deriveComplexVariableLengthValueReader(member);
		}

		throw new NotImplementedYetError();

	}

	public static ValueReader deriveComplexVariableLengthValueReader(final PersistenceTypeDefinitionMember member)
	{
		final PersistenceTypeDescriptionMemberFieldGenericComplex memberComplex = (PersistenceTypeDescriptionMemberFieldGenericComplex) member;
		final XGettingSequence members = memberComplex.members();

		if(members.size() == 1)
		{
			final PersistenceTypeDescriptionMemberFieldGeneric listMember = members.first();

			if(listMember.isReference())
			{
				return new ValueReaderReferenceList(member);
			}

			if(listMember.isPrimitive())
			{
				return new ValueReaderPrimitiveList((PersistenceTypeDefinitionMember) listMember);
			}

			if(listMember.typeName().contentEquals(PersistenceTypeDictionary.Symbols.typeChars()))
			{
				return new ValueReaderStringList((PersistenceTypeDefinitionMember) listMember);
			}

			if(listMember.typeName().contentEquals(PersistenceTypeDictionary.Symbols.typeBytes()))
			{
				return new ValueReaderPrimitiveByteList((PersistenceTypeDefinitionMember) listMember);
			}
		}
		else
		{
			return new ValueReaderArrayOfLists(member);
		}

		throw new NotImplementedYetError();
	}

	public static void readObjectValues(
			final Binary        binary      ,
			final ValueReader[] valueReaders,
			final long[]        valueOffsets,
			final ObjectDescription  objectDescription)
	{
		final Object[] objectValues = new Object[valueReaders.length];

		final List variableLength = new ArrayList<>();
		long offset = 0;
		for(int i = 0; i < objectValues.length; i++)
		{
			objectValues[i] = valueReaders[i].readValue(binary, offset);
			final long size = valueReaders[i].getBinarySize(binary, offset);
			final long variableSize = valueReaders[i].getVariableLength(binary, offset);
			offset += size;

			if(variableSize > -1)
			{
				variableLength.add(variableSize);
			}
		}

		objectDescription.setLength(objectValues.length - variableLength.size());
		objectDescription.setVariableLength(variableLength.size() > 0 ? variableLength.toArray(new Long[0]) : null);


		objectDescription.setValues(objectValues);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy