/* * 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.isis.schema.utils; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collection; import com.google.common.base.Function; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; import org.apache.isis.applib.services.bookmark.Bookmark; import org.apache.isis.applib.services.bookmark.BookmarkService; import org.apache.isis.schema.cmd.v1.ParamDto; import org.apache.isis.schema.common.v1.CollectionDto; import org.apache.isis.schema.common.v1.EnumDto; import org.apache.isis.schema.common.v1.OidDto; import org.apache.isis.schema.common.v1.ValueDto; import org.apache.isis.schema.common.v1.ValueType; import org.apache.isis.schema.common.v1.ValueWithTypeDto; import org.apache.isis.schema.utils.jaxbadapters.JavaSqlTimestampXmlGregorianCalendarAdapter; import org.apache.isis.schema.utils.jaxbadapters.JodaDateTimeXMLGregorianCalendarAdapter; import org.apache.isis.schema.utils.jaxbadapters.JodaLocalDateTimeXMLGregorianCalendarAdapter; import org.apache.isis.schema.utils.jaxbadapters.JodaLocalDateXMLGregorianCalendarAdapter; import org.apache.isis.schema.utils.jaxbadapters.JodaLocalTimeXMLGregorianCalendarAdapter; public final class CommonDtoUtils { //region > PARAM_DTO_TO_NAME, PARAM_DTO_TO_TYPE public static final Function<ParamDto, String> PARAM_DTO_TO_NAME = new Function<ParamDto, String>() { @Override public String apply(final ParamDto paramDto) { return paramDto.getName(); } }; public static final Function<ParamDto, ValueType> PARAM_DTO_TO_TYPE = new Function<ParamDto, ValueType>() { @Override public ValueType apply(final ParamDto paramDto) { return paramDto.getType(); } }; //endregion //region > asValueType private final static ImmutableMap<Class<?>, ValueType> valueTypeByClass = new ImmutableMap.Builder<Class<?>, ValueType>() .put(String.class, ValueType.STRING) .put(byte.class, ValueType.BYTE) .put(Byte.class, ValueType.BYTE) .put(short.class, ValueType.SHORT) .put(Short.class, ValueType.SHORT) .put(int.class, ValueType.INT) .put(Integer.class, ValueType.INT) .put(long.class, ValueType.LONG) .put(Long.class, ValueType.LONG) .put(char.class, ValueType.CHAR) .put(Character.class, ValueType.CHAR) .put(boolean.class, ValueType.BOOLEAN) .put(Boolean.class, ValueType.BOOLEAN) .put(float.class, ValueType.FLOAT) .put(Float.class, ValueType.FLOAT) .put(double.class, ValueType.DOUBLE) .put(Double.class, ValueType.DOUBLE) .put(BigInteger.class, ValueType.BIG_INTEGER) .put(BigDecimal.class, ValueType.BIG_DECIMAL) .put(DateTime.class, ValueType.JODA_DATE_TIME) .put(LocalDateTime.class, ValueType.JODA_LOCAL_DATE_TIME) .put(LocalDate.class, ValueType.JODA_LOCAL_DATE) .put(LocalTime.class, ValueType.JODA_LOCAL_TIME) .put(java.sql.Timestamp.class, ValueType.JAVA_SQL_TIMESTAMP) .build(); public static ValueType asValueType(final Class<?> type) { final ValueType valueType = valueTypeByClass.get(type); if (valueType != null) { return valueType; } if (type.isEnum()) { return ValueType.ENUM; } // assume reference otherwise return ValueType.REFERENCE; } //endregion //region > newValueDto, setValueOn public static ValueDto newValueDto( final ValueType valueType, final Object val, final BookmarkService bookmarkService) { if(val == null) { return null; } final ValueDto valueDto = new ValueDto(); return setValueOn(valueDto, valueType, val, bookmarkService); } public static <T extends ValueWithTypeDto> T setValueOn( final T valueWithTypeDto, final ValueType valueType, final Object val, final BookmarkService bookmarkService) { setValueOn((ValueDto)valueWithTypeDto, valueType, val, bookmarkService); valueWithTypeDto.setNull(val == null); if(val instanceof Collection) { valueWithTypeDto.setType(ValueType.COLLECTION); } return valueWithTypeDto; } public static <T extends ValueDto> T setValueOn( final T valueDto, final ValueType valueType, final Object val, final BookmarkService bookmarkService) { if(val instanceof Collection) { final Collection collection = (Collection) val; final CollectionDto collectionDto = asCollectionDto(collection, valueType, bookmarkService); valueDto.setCollection(collectionDto); return valueDto; } switch (valueType) { case STRING: { final String argValue = (String) val; valueDto.setString(argValue); return valueDto; } case BYTE: { final Byte argValue = (Byte) val; valueDto.setByte(argValue); return valueDto; } case SHORT: { final Short argValue = (Short) val; valueDto.setShort(argValue); return valueDto; } case INT: { final Integer argValue = (Integer) val; valueDto.setInt(argValue); return valueDto; } case LONG: { final Long argValue = (Long) val; valueDto.setLong(argValue); return valueDto; } case CHAR: { final Character argValue = (Character) val; valueDto.setChar("" + argValue); return valueDto; } case BOOLEAN: { final Boolean argValue = (Boolean) val; valueDto.setBoolean(argValue); return valueDto; } case FLOAT: { final Float argValue = (Float) val; valueDto.setFloat(argValue); return valueDto; } case DOUBLE: { final Double argValue = (Double) val; valueDto.setDouble(argValue); return valueDto; } case BIG_INTEGER: { final BigInteger argValue = (BigInteger) val; valueDto.setBigInteger(argValue); return valueDto; } case BIG_DECIMAL: { final BigDecimal argValue = (BigDecimal) val; valueDto.setBigDecimal(argValue); return valueDto; } case JODA_DATE_TIME: { final DateTime argValue = (DateTime) val; valueDto.setDateTime(JodaDateTimeXMLGregorianCalendarAdapter.print(argValue)); return valueDto; } case JODA_LOCAL_DATE_TIME: { final LocalDateTime argValue = (LocalDateTime) val; valueDto.setLocalDateTime(JodaLocalDateTimeXMLGregorianCalendarAdapter.print(argValue)); return valueDto; } case JODA_LOCAL_DATE: { final LocalDate argValue = (LocalDate) val; valueDto.setLocalDate(JodaLocalDateXMLGregorianCalendarAdapter.print(argValue)); return valueDto; } case JODA_LOCAL_TIME: { final LocalTime argValue = (LocalTime) val; valueDto.setLocalTime(JodaLocalTimeXMLGregorianCalendarAdapter.print(argValue)); return valueDto; } case JAVA_SQL_TIMESTAMP: { final java.sql.Timestamp argValue = (java.sql.Timestamp) val; valueDto.setTimestamp(JavaSqlTimestampXmlGregorianCalendarAdapter.print(argValue)); return valueDto; } case ENUM: { final Enum argValue = (Enum) val; if(argValue == null) { return null; } final EnumDto enumDto = new EnumDto(); valueDto.setEnum(enumDto); enumDto.setEnumType(argValue.getClass().getName()); enumDto.setEnumName(argValue.name()); return valueDto; } case REFERENCE: { final Bookmark bookmark = val instanceof Bookmark ? (Bookmark) val : bookmarkService.bookmarkFor(val); if (bookmark != null) { OidDto argValue = bookmark.toOidDto(); valueDto.setReference(argValue); } return valueDto; } case VOID: { return null; } default: // should never happen; all cases are listed above throw new IllegalArgumentException(String.format( "newValueDto(): do not recognize valueType %s (likely a framework error)", valueType)); } } private static CollectionDto asCollectionDto( final Iterable iterable, final ValueType valueType, final BookmarkService bookmarkService) { final CollectionDto collectionDto = new CollectionDto(); collectionDto.setType(valueType); for (Object o : iterable) { final ValueDto valueDto = new ValueDto(); setValueOn(valueDto, valueType, o, bookmarkService); collectionDto.getValue().add(valueDto); } return collectionDto; } //endregion //region > getValue (from valueDto) public static <T> T getValue( final ValueDto valueDto, final ValueType valueType) { switch(valueType) { case STRING: return (T) valueDto.getString(); case BYTE: return (T) valueDto.getByte(); case SHORT: return (T) valueDto.getShort(); case INT: return (T) valueDto.getInt(); case LONG: return (T) valueDto.getLong(); case FLOAT: return (T) valueDto.getFloat(); case DOUBLE: return (T) valueDto.getDouble(); case BOOLEAN: return (T) valueDto.isBoolean(); case CHAR: final String aChar = valueDto.getChar(); if(Strings.isNullOrEmpty(aChar)) { return null; } return (T) (Object)aChar.charAt(0); case BIG_DECIMAL: return (T) valueDto.getBigDecimal(); case BIG_INTEGER: return (T) valueDto.getBigInteger(); case JAVA_SQL_TIMESTAMP: return (T) JavaSqlTimestampXmlGregorianCalendarAdapter.parse(valueDto.getDateTime()); case JODA_DATE_TIME: return (T) JodaDateTimeXMLGregorianCalendarAdapter.parse(valueDto.getDateTime()); case JODA_LOCAL_DATE: return (T) JodaLocalDateXMLGregorianCalendarAdapter.parse(valueDto.getLocalDate()); case JODA_LOCAL_DATE_TIME: return (T) JodaLocalDateTimeXMLGregorianCalendarAdapter.parse(valueDto.getLocalDateTime()); case JODA_LOCAL_TIME: return (T) JodaLocalTimeXMLGregorianCalendarAdapter.parse(valueDto.getLocalTime()); case ENUM: final EnumDto enumDto = valueDto.getEnum(); final String enumType = enumDto.getEnumType(); final Class<? extends Enum> enumClass = loadClassElseThrow(enumType); return (T) Enum.valueOf(enumClass, enumDto.getEnumName()); case REFERENCE: return (T) valueDto.getReference(); case VOID: return null; default: // should never happen; all cases are listed above throw new IllegalArgumentException(String.format( "getValueDto(...): do not recognize valueType %s (likely a framework error)", valueType)); } } private static <T> Class<T> loadClassElseThrow(final String enumType) { try { return (Class<T>) loadClass(enumType); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } private static Class<?> loadClass(String className) throws ClassNotFoundException { ClassLoader ccl = Thread.currentThread().getContextClassLoader(); if(ccl == null) { return loadClass(className, (ClassLoader)null); } else { try { return loadClass(className, ccl); } catch (ClassNotFoundException var3) { return loadClass(className, (ClassLoader)null); } } } private static Class<?> loadClass(String className, ClassLoader classLoader) throws ClassNotFoundException { return classLoader == null?Class.forName(className):Class.forName(className, true, classLoader); } //endregion //region > newValueWithTypeDto public static ValueWithTypeDto newValueWithTypeDto( final Class<?> type, final Object val, final BookmarkService bookmarkService) { final ValueWithTypeDto valueWithTypeDto = new ValueWithTypeDto(); final ValueType valueType = asValueType(type); valueWithTypeDto.setType(valueType); setValueOn(valueWithTypeDto, valueType, val, bookmarkService); return valueWithTypeDto; } //endregion //region > getValue (from ValueWithTypeDto) public static <T> T getValue(final ValueWithTypeDto valueWithTypeDto) { if(valueWithTypeDto.isNull()) { return null; } final ValueType type = valueWithTypeDto.getType(); return CommonDtoUtils.getValue(valueWithTypeDto, type); } //endregion //region > newParamDto public static ParamDto newParamDto( final String parameterName, final Class<?> parameterType, final Object arg, final BookmarkService bookmarkService) { final ParamDto paramDto = new ParamDto(); paramDto.setName(parameterName); final ValueType valueType = CommonDtoUtils.asValueType(parameterType); paramDto.setType(valueType); CommonDtoUtils.setValueOn(paramDto, valueType, arg, bookmarkService); return paramDto; } //endregion //region > getValue (from ParamDto) public static <T> T getValue(final ParamDto paramDto) { if(paramDto.isNull()) { return null; } final ValueType parameterType = paramDto.getType(); return CommonDtoUtils.getValue(paramDto, parameterType); } //endregion }