<commit_before>//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// This file is a part of the 'esoco-storage' project.
// Copyright 2018 <NAME>, esoco GmbH, Flensburg, Germany
//
// Licensed 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 de.esoco.storage.mapping;

import de.esoco.lib.datatype.Period;
import de.esoco.lib.expression.Conversions;
import de.esoco.lib.logging.Log;
import de.esoco.lib.manage.TransactionManager;
import de.esoco.lib.property.HasOrder;
import de.esoco.lib.reflect.ReflectUtil;

import de.esoco.storage.Storage;
import de.esoco.storage.StorageException;
import de.esoco.storage.StorageManager;
import de.esoco.storage.StorageMapping;

import java.math.BigDecimal;
import java.math.BigInteger;

import java.util.Collection;
import java.util.Map;

import org.obrel.core.Relatable;
import org.obrel.core.RelatedObject;
import org.obrel.core.RelationType;

import static de.esoco.lib.expression.Conversions.parseCollection;
import static de.esoco.lib.expression.Conversions.parseMap;

import static org.obrel.type.MetaTypes.ELEMENT_DATATYPE;
import static org.obrel.type.MetaTypes.KEY_DATATYPE;
import static org.obrel.type.MetaTypes.ORDERED;
import static org.obrel.type.MetaTypes.VALUE_DATATYPE;


/********************************************************************
 * An abstract base class for storage mapping implementations. Contains some
 * generic helper methods for the implementation of mappings.
 *
 * @author eso
 */
public abstract class AbstractStorageMapping<T, A extends Relatable,
											 C extends StorageMapping<?, A, ?>>
	extends RelatedObject implements StorageMapping<T, A, C>
{
	//~ Methods ----------------------------------------------------------------

	/***************************************
	 * Implemented to perform value conversions to some standard datatypes. This
	 * especially includes string parsing and primitive datatype wrapping. The
	 * supported string conversions are
	 *
	 * <ul>
	 *   <li>Datatype {@link Class}: {@link Class#forName(String)}</li>
	 *   <li>Datatype {@link RelationType}: {@link
	 *     RelationType#valueOf(String)}</li>
	 *   <li>Enums: {@link Enum#valueOf(Class, String)} with handling of {@link
	 *     HasOrder} prefixes</li>
	 *   <li>Datatype {@link Period}: {@link Period#valueOf(String)}</li>
	 *   <li>Datatype {@link Collection}: {@link
	 *     Conversions#parseCollection(String, Class, Class, boolean)}</li>
	 *   <li>Datatype {@link Map}: {@link Conversions#parseMap(String, Class,
	 *     Class, Class, boolean)}</li>
	 *   <li>Any datatype that has either a constructor with a String parameter
	 *     or a valueOf(String) method.</li>
	 * </ul>
	 *
	 * @see StorageMapping#checkAttributeValue(Relatable, Object)
	 */
	@Override
	public Object checkAttributeValue(A rAttribute, Object rValue)
		throws StorageException
	{
		if (rValue != null)
		{
			Class<?> rDatatype = getAttributeDatatype(rAttribute);

			if (rDatatype != String.class)
			{
				if (rValue instanceof String)
				{
					rValue =
						parseStringValue(rAttribute,
										 rDatatype,
										 (String) rValue);
				}
				else if (rDatatype == Integer.class && rValue instanceof Long)
				{
					// map long values to integer if value is in the integer range
					// this is a fix for MySQL which produces long IDs in views
					// under some circumstances

					long nLong = ((Long) rValue).longValue();

					if (nLong <= Integer.MAX_VALUE &&
						nLong >= Integer.MIN_VALUE)
					{
						rValue = Integer.valueOf((int) nLong);
					}
				}
				else if (rDatatype == BigInteger.class &&
						 rValue instanceof BigDecimal)
				{
					// large integer attributes may be stored as decimal values
					// without a fraction (e.g. SQL NUMERIC type)
					rValue = ((BigDecimal) rValue).toBigIntegerExact();
				}
			}

			Class<?> rValueType = rValue.getClass();

			if (rDatatype.isPrimitive())
			{
				rDatatype = ReflectUtil.getWrapperType(rDatatype);
			}

			if (!rDatatype.isAssignableFrom(rValueType))
			{
				String sMessage =
					String.format("Attribute type mismatch: %s (expected: %s)",
								  rValueType,
								  rDatatype);

				throw new IllegalArgumentException(sMessage);
			}
		}

		return rValue;
	}
<commit_msg>BF: backwards compatibility for long IDs<commit_after>//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// This file is a part of the 'esoco-storage' project.
// Copyright 2018 <NAME>, esoco GmbH, Flensburg, Germany
//
// Licensed 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 de.esoco.storage.mapping;

import de.esoco.lib.datatype.Period;
import de.esoco.lib.expression.Conversions;
import de.esoco.lib.logging.Log;
import de.esoco.lib.manage.TransactionManager;
import de.esoco.lib.property.HasOrder;
import de.esoco.lib.reflect.ReflectUtil;

import de.esoco.storage.Storage;
import de.esoco.storage.StorageException;
import de.esoco.storage.StorageManager;
import de.esoco.storage.StorageMapping;

import java.math.BigDecimal;
import java.math.BigInteger;

import java.util.Collection;
import java.util.Map;

import org.obrel.core.Relatable;
import org.obrel.core.RelatedObject;
import org.obrel.core.RelationType;

import static de.esoco.lib.expression.Conversions.parseCollection;
import static de.esoco.lib.expression.Conversions.parseMap;

import static org.obrel.type.MetaTypes.ELEMENT_DATATYPE;
import static org.obrel.type.MetaTypes.KEY_DATATYPE;
import static org.obrel.type.MetaTypes.ORDERED;
import static org.obrel.type.MetaTypes.VALUE_DATATYPE;


/********************************************************************
 * An abstract base class for storage mapping implementations. Contains some
 * generic helper methods for the implementation of mappings.
 *
 * @author eso
 */
public abstract class AbstractStorageMapping<T, A extends Relatable,
											 C extends StorageMapping<?, A, ?>>
	extends RelatedObject implements StorageMapping<T, A, C>
{
	//~ Methods ----------------------------------------------------------------

	/***************************************
	 * Implemented to perform value conversions to some standard datatypes. This
	 * especially includes string parsing and primitive datatype wrapping. The
	 * supported string conversions are
	 *
	 * <ul>
	 *   <li>Datatype {@link Class}: {@link Class#forName(String)}</li>
	 *   <li>Datatype {@link RelationType}: {@link
	 *     RelationType#valueOf(String)}</li>
	 *   <li>Enums: {@link Enum#valueOf(Class, String)} with handling of {@link
	 *     HasOrder} prefixes</li>
	 *   <li>Datatype {@link Period}: {@link Period#valueOf(String)}</li>
	 *   <li>Datatype {@link Collection}: {@link
	 *     Conversions#parseCollection(String, Class, Class, boolean)}</li>
	 *   <li>Datatype {@link Map}: {@link Conversions#parseMap(String, Class,
	 *     Class, Class, boolean)}</li>
	 *   <li>Any datatype that has either a constructor with a String parameter
	 *     or a valueOf(String) method.</li>
	 * </ul>
	 *
	 * @see StorageMapping#checkAttributeValue(Relatable, Object)
	 */
	@Override
	public Object checkAttributeValue(A rAttribute, Object rValue)
		throws StorageException
	{
		if (rValue != null)
		{
			Class<?> rDatatype = getAttributeDatatype(rAttribute);

			if (rDatatype != String.class)
			{
				if (rDatatype.isPrimitive())
				{
					rDatatype = ReflectUtil.getWrapperType(rDatatype);
				}

				if (rValue instanceof String)
				{
					rValue =
						parseStringValue(rAttribute,
										 rDatatype,
										 (String) rValue);
				}
				else if (rDatatype == Long.class && rValue instanceof Number)
				{
					rValue = ((Number) rValue).longValue();
				}
				else if (rDatatype == BigInteger.class &&
						 rValue instanceof BigDecimal)
				{
					// large integer attributes may be stored as decimal values
					// without a fraction (e.g. SQL NUMERIC type)
					rValue = ((BigDecimal) rValue).toBigIntegerExact();
				}
			}

			Class<?> rValueType = rValue.getClass();

			if (!rDatatype.isAssignableFrom(rValueType))
			{
				String sMessage =
					String.format("Attribute type mismatch: %s (expected: %s)",
								  rValueType,
								  rDatatype);

				throw new IllegalArgumentException(sMessage);
			}
		}

		return rValue;
	}

{'fraction_non_alphanumeric': 0.17202469661486056, 'fraction_numerical': 0.0017032148179689163, 'mean_word_length': 3.641798418972332, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6000333', 'n_tokens_mistral': 3079, 'n_tokens_neox': 2621, 'n_words': 759}