blob: 6c45db2739e29e2108fe44d73811420870f5e92f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.polygene.api.type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
import org.apache.polygene.api.entity.EntityReference;
import org.apache.polygene.api.identity.Identity;
import static java.util.stream.Collectors.joining;
/**
* Base class for types of values in ValueComposites and Properties.
*/
public class ValueType implements HasTypes
{
public static final ValueType OBJECT = ValueType.of( Object.class );
public static final ValueType STRING = ValueType.of( String.class );
public static final ValueType CHARACTER = ValueType.of( Character.class, char.class );
public static final ValueType BOOLEAN = ValueType.of( Boolean.class, boolean.class );
public static final ValueType INTEGER = ValueType.of( Integer.class, int.class );
public static final ValueType SHORT = ValueType.of( Short.class, short.class );
public static final ValueType LONG = ValueType.of( Long.class, long.class );
public static final ValueType BYTE = ValueType.of( Byte.class, byte.class );
public static final ValueType FLOAT = ValueType.of( Float.class, float.class );
public static final ValueType DOUBLE = ValueType.of( Double.class, double.class );
public static final ValueType BIG_DECIMAL = ValueType.of( BigDecimal.class );
public static final ValueType BIG_INTEGER = ValueType.of( BigInteger.class );
public static final ValueType INSTANT = ValueType.of( Instant.class );
public static final ValueType ZONED_DATE_TIME = ValueType.of( ZonedDateTime.class );
public static final ValueType OFFSET_DATE_TIME = ValueType.of( OffsetDateTime.class );
public static final ValueType LOCAL_DATE_TIME = ValueType.of( LocalDateTime.class );
public static final ValueType LOCAL_DATE = ValueType.of( LocalDate.class );
public static final ValueType LOCAL_TIME = ValueType.of( LocalTime.class );
public static final ValueType DURATION = ValueType.of( Duration.class );
public static final ValueType PERIOD = ValueType.of( Period.class );
public static final ValueType IDENTITY = ValueType.of( Identity.class );
public static final ValueType ENTITY_REFERENCE = ValueType.of( EntityReference.class );
public static ValueType of( Class<?>... types )
{
return new ValueType( types );
}
protected final List<Class<?>> types;
protected ValueType( Class<?>... types )
{
this( Arrays.asList( types ) );
}
protected ValueType( List<Class<?>> types )
{
this.types = applyPrimitiveAndBoxedTypes( types );
}
private List<Class<?>> applyPrimitiveAndBoxedTypes( List<Class<?>> types )
{
int charPrimitiveIndex = types.indexOf( char.class );
int charBoxedIndex = types.indexOf( Character.class );
int boolPrimitiveIndex = types.indexOf( boolean.class );
int boolBoxedIndex = types.indexOf( Boolean.class );
int intPrimitiveIndex = types.indexOf( int.class );
int intBoxedIndex = types.indexOf( Integer.class );
int shortPrimitiveIndex = types.indexOf( short.class );
int shortBoxedIndex = types.indexOf( Short.class );
int longPrimitiveIndex = types.indexOf( long.class );
int longBoxedIndex = types.indexOf( Long.class );
int bytePrimitiveIndex = types.indexOf( byte.class );
int byteBoxedIndex = types.indexOf( Byte.class );
int floatPrimitiveIndex = types.indexOf( float.class );
int floatBoxedIndex = types.indexOf( Float.class );
int doublePrimitiveIndex = types.indexOf( double.class );
int doubleBoxedIndex = types.indexOf( Double.class );
if( charPrimitiveIndex == -1 && charBoxedIndex == -1
&& boolPrimitiveIndex == -1 && boolBoxedIndex == -1
&& intPrimitiveIndex == -1 && intBoxedIndex == -1
&& shortPrimitiveIndex == -1 && shortBoxedIndex == -1
&& longPrimitiveIndex == -1 && longBoxedIndex == -1
&& bytePrimitiveIndex == -1 && byteBoxedIndex == -1
&& floatPrimitiveIndex == -1 && floatBoxedIndex == -1
&& doublePrimitiveIndex == -1 && doubleBoxedIndex == -1 )
{
return types;
}
List<Class<?>> allTypes = new ArrayList<>( types );
if( charPrimitiveIndex >= 0 && charBoxedIndex == -1 ) { allTypes.add( Character.class ); }
if( charPrimitiveIndex == -1 && charBoxedIndex >= 0 ) { allTypes.add( char.class ); }
if( boolPrimitiveIndex >= 0 && boolBoxedIndex == -1 ) { allTypes.add( Boolean.class ); }
if( boolPrimitiveIndex == -1 && boolBoxedIndex >= 0 ) { allTypes.add( boolean.class ); }
if( intPrimitiveIndex >= 0 && intBoxedIndex == -1 ) { allTypes.add( Integer.class ); }
if( intPrimitiveIndex == -1 && intBoxedIndex >= 0 ) { allTypes.add( int.class ); }
if( shortPrimitiveIndex >= 0 && shortBoxedIndex == -1 ) { allTypes.add( Short.class ); }
if( shortPrimitiveIndex == -1 && shortBoxedIndex >= 0 ) { allTypes.add( short.class ); }
if( longPrimitiveIndex >= 0 && longBoxedIndex == -1 ) { allTypes.add( Long.class ); }
if( longPrimitiveIndex == -1 && longBoxedIndex >= 0 ) { allTypes.add( long.class ); }
if( bytePrimitiveIndex >= 0 && byteBoxedIndex == -1 ) { allTypes.add( Byte.class ); }
if( bytePrimitiveIndex == -1 && byteBoxedIndex >= 0 ) { allTypes.add( byte.class ); }
if( floatPrimitiveIndex >= 0 && floatBoxedIndex == -1 ) { allTypes.add( Float.class ); }
if( floatPrimitiveIndex == -1 && floatBoxedIndex >= 0 ) { allTypes.add( float.class ); }
if( doublePrimitiveIndex >= 0 && doubleBoxedIndex == -1 ) { allTypes.add( Double.class ); }
if( doublePrimitiveIndex == -1 && doubleBoxedIndex >= 0 ) { allTypes.add( double.class ); }
return allTypes;
}
public Class<?> primaryType()
{
return types.stream().findFirst().orElse( null );
}
@Override
public Stream<Class<?>> types()
{
return types.stream();
}
@Override
public boolean equals( Object o )
{
if( this == o ) { return true; }
if( o == null || getClass() != o.getClass() ) { return false; }
ValueType valueType = (ValueType) o;
return Objects.equals( types, valueType.types );
}
@Override
public int hashCode()
{
return Objects.hash( types );
}
@Override
public String toString()
{
String name = types.stream().map( Class::getName ).collect( joining( "," ) );
if( name.contains( "," ) )
{
name = '{' + name + '}';
}
return name;
}
}