Checkpoint - class-detecting loader handling generic loaders; generic loader created & working; Loader registry moved to its own class;

This commit is contained in:
2025-01-16 14:08:32 -06:00
parent f147516e45
commit 3f4d11b22a
7 changed files with 393 additions and 163 deletions

View File

@ -31,21 +31,17 @@ import java.lang.reflect.Type;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.kingsrook.qqq.backend.core.instances.loaders.implementations.QTableMetaDataLoader;
import com.kingsrook.qqq.backend.core.logging.QLogger; import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject; import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject;
import com.kingsrook.qqq.backend.core.utils.ClassPathUtils;
import com.kingsrook.qqq.backend.core.utils.JsonUtils; import com.kingsrook.qqq.backend.core.utils.JsonUtils;
import com.kingsrook.qqq.backend.core.utils.StringUtils; import com.kingsrook.qqq.backend.core.utils.StringUtils;
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
import com.kingsrook.qqq.backend.core.utils.YamlUtils; import com.kingsrook.qqq.backend.core.utils.YamlUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import static com.kingsrook.qqq.backend.core.utils.ValueUtils.getValueAsBoolean; import static com.kingsrook.qqq.backend.core.utils.ValueUtils.getValueAsBoolean;
@ -61,33 +57,6 @@ public abstract class AbstractMetaDataLoader<T extends QMetaDataObject>
{ {
private static final QLogger LOG = QLogger.getLogger(AbstractMetaDataLoader.class); private static final QLogger LOG = QLogger.getLogger(AbstractMetaDataLoader.class);
private static Map<Class<?>, Class<? extends AbstractMetaDataLoader<?>>> registeredLoaders = new HashMap<>();
static
{
try
{
List<Class<?>> classesInPackage = ClassPathUtils.getClassesInPackage(QTableMetaDataLoader.class.getPackageName());
for(Class<?> loaderClass : classesInPackage)
{
Type superClass = loaderClass.getGenericSuperclass();
if(superClass.getTypeName().startsWith(AbstractMetaDataLoader.class.getName() + "<"))
// if(superClass instanceof Class<?> c && AbstractMetaDataLoader.class.isAssignableFrom(c))
{
Type actualTypeArgument = ((ParameterizedType) superClass).getActualTypeArguments()[0];
Class<?> metaDataObjectType = Class.forName(actualTypeArgument.getTypeName());
registeredLoaders.put(metaDataObjectType, (Class<? extends AbstractMetaDataLoader<?>>) loaderClass);
}
}
System.out.println("Registered loaders: " + registeredLoaders);
}
catch(Exception e)
{
LOG.error("Error in static init block for AbstractMetaDataLoader", e);
}
}
private String fileName; private String fileName;
@ -185,7 +154,7 @@ public abstract class AbstractMetaDataLoader<T extends QMetaDataObject>
/*************************************************************************** /***************************************************************************
* *
***************************************************************************/ ***************************************************************************/
private Object reflectivelyMapValue(QInstance qInstance, Method method, Class<?> parameterType, Object rawValue) throws Exception public Object reflectivelyMapValue(QInstance qInstance, Method method, Class<?> parameterType, Object rawValue) throws Exception
{ {
if(parameterType.equals(String.class)) if(parameterType.equals(String.class))
{ {
@ -212,8 +181,7 @@ public abstract class AbstractMetaDataLoader<T extends QMetaDataObject>
Type actualTypeArgument = ((ParameterizedType) method.getGenericParameterTypes()[0]).getActualTypeArguments()[0]; Type actualTypeArgument = ((ParameterizedType) method.getGenericParameterTypes()[0]).getActualTypeArguments()[0];
Class<?> actualTypeClass = Class.forName(actualTypeArgument.getTypeName()); Class<?> actualTypeClass = Class.forName(actualTypeArgument.getTypeName());
Object value = rawValue; if(rawValue instanceof @SuppressWarnings("rawtypes")List valueList)
if(value instanceof List valueList)
{ {
List<Object> mappedValueList = new ArrayList<>(); List<Object> mappedValueList = new ArrayList<>();
for(Object o : valueList) for(Object o : valueList)
@ -236,8 +204,7 @@ public abstract class AbstractMetaDataLoader<T extends QMetaDataObject>
Type actualTypeArgument = ((ParameterizedType) method.getGenericParameterTypes()[0]).getActualTypeArguments()[0]; Type actualTypeArgument = ((ParameterizedType) method.getGenericParameterTypes()[0]).getActualTypeArguments()[0];
Class<?> actualTypeClass = Class.forName(actualTypeArgument.getTypeName()); Class<?> actualTypeClass = Class.forName(actualTypeArgument.getTypeName());
Object value = rawValue; if(rawValue instanceof @SuppressWarnings("rawtypes")List valueList)
if(value instanceof List valueList)
{ {
Set<Object> mappedValueSet = new LinkedHashSet<>(); Set<Object> mappedValueSet = new LinkedHashSet<>();
for(Object o : valueList) for(Object o : valueList)
@ -268,14 +235,14 @@ public abstract class AbstractMetaDataLoader<T extends QMetaDataObject>
Type actualTypeArgument = ((ParameterizedType) method.getGenericParameterTypes()[0]).getActualTypeArguments()[1]; Type actualTypeArgument = ((ParameterizedType) method.getGenericParameterTypes()[0]).getActualTypeArguments()[1];
Class<?> actualTypeClass = Class.forName(actualTypeArgument.getTypeName()); Class<?> actualTypeClass = Class.forName(actualTypeArgument.getTypeName());
Object value = rawValue; if(rawValue instanceof @SuppressWarnings("rawtypes")Map valueMap)
if(value instanceof Map valueMap)
{ {
Map<String, Object> mappedValueMap = new LinkedHashMap<>(); Map<String, Object> mappedValueMap = new LinkedHashMap<>();
for(Object o : valueMap.entrySet()) for(Object o : valueMap.entrySet())
{ {
try try
{ {
@SuppressWarnings("unchecked")
Map.Entry<String, Object> entry = (Map.Entry<String, Object>) o; Map.Entry<String, Object> entry = (Map.Entry<String, Object>) o;
Object mappedValue = reflectivelyMapValue(qInstance, null, actualTypeClass, entry.getValue()); Object mappedValue = reflectivelyMapValue(qInstance, null, actualTypeClass, entry.getValue());
mappedValueMap.put(entry.getKey(), mappedValue); mappedValueMap.put(entry.getKey(), mappedValue);
@ -299,23 +266,22 @@ public abstract class AbstractMetaDataLoader<T extends QMetaDataObject>
} }
} }
} }
else if(registeredLoaders.containsKey(parameterType)) else if(MetaDataLoaderRegistry.hasLoaderForClass(parameterType))
{ {
Object value = rawValue; if(rawValue instanceof @SuppressWarnings("rawtypes")Map valueMap)
if(value instanceof Map valueMap)
{ {
Class<? extends AbstractMetaDataLoader<?>> loaderClass = registeredLoaders.get(parameterType); Class<? extends AbstractMetaDataLoader<?>> loaderClass = MetaDataLoaderRegistry.getLoaderForClass(parameterType);
AbstractMetaDataLoader<?> loader = loaderClass.getConstructor().newInstance(); AbstractMetaDataLoader<?> loader = loaderClass.getConstructor().newInstance();
QMetaDataObject loadedValue = loader.mapToMetaDataObject(qInstance, valueMap); //noinspection unchecked
return (loadedValue); return (loader.mapToMetaDataObject(qInstance, valueMap));
} }
} }
else if(QMetaDataObject.class.isAssignableFrom(parameterType)) else if(QMetaDataObject.class.isAssignableFrom(parameterType))
{ {
Object value = rawValue; if(rawValue instanceof @SuppressWarnings("rawtypes")Map valueMap)
if(value instanceof Map valueMap)
{ {
QMetaDataObject childObject = (QMetaDataObject) parameterType.getConstructor().newInstance(); QMetaDataObject childObject = (QMetaDataObject) parameterType.getConstructor().newInstance();
//noinspection unchecked
reflectivelyMap(qInstance, childObject, valueMap); reflectivelyMap(qInstance, childObject, valueMap);
return (childObject); return (childObject);
} }
@ -340,117 +306,96 @@ public abstract class AbstractMetaDataLoader<T extends QMetaDataObject>
throw new NoValueException(); throw new NoValueException();
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// unclear if the below is needed. if so, useful to not re-write, but is hurting test coverage, so zombie until used //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///***************************************************************************
// *
// ***************************************************************************/
//protected ListOfMapOrMapOfMap getListOfMapOrMapOfMap(Map<String, Object> map, String key)
//{
// if(map.containsKey(key))
// {
// if(map.get(key) instanceof List)
// {
// return (new ListOfMapOrMapOfMap((List<Map<String, Object>>) map.get(key)));
// }
// else if(map.get(key) instanceof Map)
// {
// return (new ListOfMapOrMapOfMap((Map<String, Map<String, Object>>) map.get(key)));
// }
// else
// {
// LOG.warn("Expected list or map under key [" + key + "] while processing [" + getClass().getSimpleName() + "] from [" + fileName + "], but found: " + (map.get(key) == null ? "null" : map.get(key).getClass().getSimpleName()));
// }
// }
// return (null);
//}
/*************************************************************************** ///***************************************************************************
* // *
***************************************************************************/ // ***************************************************************************/
protected ListOfMapOrMapOfMap getListOfMapOrMapOfMap(Map<String, Object> map, String key) //protected List<Map<String, Object>> getListOfMap(Map<String, Object> map, String key)
{ //{
if(map.containsKey(key)) // if(map.containsKey(key))
{ // {
if(map.get(key) instanceof List) // if(map.get(key) instanceof List)
{ // {
return (new ListOfMapOrMapOfMap((List<Map<String, Object>>) map.get(key))); // return (List<Map<String, Object>>) map.get(key);
} // }
else if(map.get(key) instanceof Map) // else
{ // {
return (new ListOfMapOrMapOfMap((Map<String, Map<String, Object>>) map.get(key))); // LOG.warn("Expected list under key [" + key + "] while processing [" + getClass().getSimpleName() + "] from [" + fileName + "], but found: " + (map.get(key) == null ? "null" : map.get(key).getClass().getSimpleName()));
} // }
else // }
{
LOG.warn("Expected list or map under key [" + key + "] while processing [" + getClass().getSimpleName() + "] from [" + fileName + "], but found: " + (map.get(key) == null ? "null" : map.get(key).getClass().getSimpleName()));
}
}
return (null); // return (null);
} //}
///***************************************************************************
// *
// ***************************************************************************/
//protected Map<String, Map<String, Object>> getMapOfMap(Map<String, Object> map, String key)
//{
// if(map.containsKey(key))
// {
// if(map.get(key) instanceof Map)
// {
// return (Map<String, Map<String, Object>>) map.get(key);
// }
// else
// {
// LOG.warn("Expected map under key [" + key + "] while processing [" + getClass().getSimpleName() + "] from [" + fileName + "], but found: " + (map.get(key) == null ? "null" : map.get(key).getClass().getSimpleName()));
// }
// }
// return (null);
//}
/*************************************************************************** ///***************************************************************************
* // **
***************************************************************************/ // ***************************************************************************/
protected List<Map<String, Object>> getListOfMap(Map<String, Object> map, String key) //protected record ListOfMapOrMapOfMap(List<Map<String, Object>> listOf, Map<String, Map<String, Object>> mapOf)
{ //{
if(map.containsKey(key)) // /*******************************************************************************
{ // ** Constructor
if(map.get(key) instanceof List) // **
{ // *******************************************************************************/
return (List<Map<String, Object>>) map.get(key); // public ListOfMapOrMapOfMap(List<Map<String, Object>> listOf)
} // {
else // this(listOf, null);
{ // }
LOG.warn("Expected list under key [" + key + "] while processing [" + getClass().getSimpleName() + "] from [" + fileName + "], but found: " + (map.get(key) == null ? "null" : map.get(key).getClass().getSimpleName()));
}
}
return (null); // /*******************************************************************************
} // ** Constructor
// **
// *******************************************************************************/
// public ListOfMapOrMapOfMap(Map<String, Map<String, Object>> mapOf)
/*************************************************************************** // {
* // this(null, mapOf);
***************************************************************************/ // }
protected Map<String, Map<String, Object>> getMapOfMap(Map<String, Object> map, String key) //}
{
if(map.containsKey(key))
{
if(map.get(key) instanceof Map)
{
return (Map<String, Map<String, Object>>) map.get(key);
}
else
{
LOG.warn("Expected map under key [" + key + "] while processing [" + getClass().getSimpleName() + "] from [" + fileName + "], but found: " + (map.get(key) == null ? "null" : map.get(key).getClass().getSimpleName()));
}
}
return (null);
}
/***************************************************************************
**
***************************************************************************/
protected record ListOfMapOrMapOfMap(List<Map<String, Object>> listOf, Map<String, Map<String, Object>> mapOf)
{
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public ListOfMapOrMapOfMap(List<Map<String, Object>> listOf)
{
this(listOf, null);
}
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public ListOfMapOrMapOfMap(Map<String, Map<String, Object>> mapOf)
{
this(null, mapOf);
}
}
/***************************************************************************
**
***************************************************************************/
protected void warnNotImplemented(Map<String, Object> map, String key)
{
if(StringUtils.hasContent(ValueUtils.getValueAsString(map.get(key))))
{
LOG.warn("Unsupported meta-data attribute [" + key + "] found while processing [" + getClass().getSimpleName() + "] from [" + fileName + "]");
}
}

View File

@ -23,10 +23,12 @@ package com.kingsrook.qqq.backend.core.instances.loaders;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
import java.util.Map; import java.util.Map;
import com.kingsrook.qqq.backend.core.instances.loaders.implementations.QTableMetaDataLoader; import com.kingsrook.qqq.backend.core.instances.loaders.implementations.GenericMetaDataLoader;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject; import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject;
import com.kingsrook.qqq.backend.core.utils.ClassPathUtils;
import com.kingsrook.qqq.backend.core.utils.ValueUtils; import com.kingsrook.qqq.backend.core.utils.ValueUtils;
@ -57,18 +59,43 @@ public class ClassDetectingMetaDataLoader extends AbstractMetaDataLoader<QMetaDa
if(map.containsKey("class")) if(map.containsKey("class"))
{ {
String classProperty = ValueUtils.getValueAsString(map.get("class")); String classProperty = ValueUtils.getValueAsString(map.get("class"));
AbstractMetaDataLoader<?> loader = switch(classProperty) try
{ {
case "QTableMetaData" -> new QTableMetaDataLoader();
// todo!! case "QTableMetaData" -> new QTableMetaDataLoader();
default -> throw new QMetaDataLoaderException("Unexpected class [" + classProperty + "] specified in " + getFileName());
};
return (loader); if(MetaDataLoaderRegistry.hasLoaderForSimpleName(classProperty))
{
Class<? extends AbstractMetaDataLoader<?>> loaderClass = MetaDataLoaderRegistry.getLoaderForSimpleName(classProperty);
return (loaderClass.getConstructor().newInstance());
} }
else
{
List<Class<?>> classesInPackage = ClassPathUtils.getClassesInPackage("com.kingsrook.qqq.backend.core.model");
for(Class<?> c : classesInPackage)
{
if(c.getSimpleName().equals(classProperty) && QMetaDataObject.class.isAssignableFrom(c))
{
@SuppressWarnings("unchecked")
Class<? extends QMetaDataObject> metaDataClass = (Class<? extends QMetaDataObject>) c;
return new GenericMetaDataLoader<>(metaDataClass);
}
}
}
throw new QMetaDataLoaderException("Unexpected class [" + classProperty + "] (not a QMetaDataObject; doesn't have a registered MetaDataLoader) specified in " + getFileName());
}
catch(QMetaDataLoaderException qmdle)
{
throw (qmdle);
}
catch(Exception e)
{
throw new QMetaDataLoaderException("Error handling class [" + classProperty + "] specified in " + getFileName(), e);
}
}
else
{
throw new QMetaDataLoaderException("Cannot detect meta-data type, because [class] attribute was not specified in file: " + getFileName()); throw new QMetaDataLoaderException("Cannot detect meta-data type, because [class] attribute was not specified in file: " + getFileName());
} }
}

View File

@ -0,0 +1,99 @@
package com.kingsrook.qqq.backend.core.instances.loaders;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.kingsrook.qqq.backend.core.instances.loaders.implementations.QTableMetaDataLoader;
import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.utils.ClassPathUtils;
/*******************************************************************************
**
*******************************************************************************/
public class MetaDataLoaderRegistry
{
private static final QLogger LOG = QLogger.getLogger(AbstractMetaDataLoader.class);
private static final Map<Class<?>, Class<? extends AbstractMetaDataLoader<?>>> registeredLoaders = new HashMap<>();
private static final Map<String, Class<? extends AbstractMetaDataLoader<?>>> registeredLoadersByTargetSimpleName = new HashMap<>();
static
{
try
{
List<Class<?>> classesInPackage = ClassPathUtils.getClassesInPackage(QTableMetaDataLoader.class.getPackageName());
for(Class<?> possibleLoaderClass : classesInPackage)
{
try
{
Type superClass = possibleLoaderClass.getGenericSuperclass();
if(superClass.getTypeName().startsWith(AbstractMetaDataLoader.class.getName() + "<"))
{
Type actualTypeArgument = ((ParameterizedType) superClass).getActualTypeArguments()[0];
if(actualTypeArgument instanceof Class)
{
//noinspection unchecked
Class<? extends AbstractMetaDataLoader<?>> loaderClass = (Class<? extends AbstractMetaDataLoader<?>>) possibleLoaderClass;
Class<?> metaDataObjectType = Class.forName(actualTypeArgument.getTypeName());
registeredLoaders.put(metaDataObjectType, loaderClass);
registeredLoadersByTargetSimpleName.put(metaDataObjectType.getSimpleName(), loaderClass);
}
}
}
catch(Exception e)
{
LOG.info("Error on class: " + possibleLoaderClass, e);
}
}
System.out.println("Registered loaders: " + registeredLoadersByTargetSimpleName);
}
catch(Exception e)
{
LOG.error("Error in static init block for MetaDataLoaderRegistry", e);
}
}
/***************************************************************************
**
***************************************************************************/
public static boolean hasLoaderForClass(Class<?> metaDataClass)
{
return registeredLoaders.containsKey(metaDataClass);
}
/***************************************************************************
**
***************************************************************************/
public static Class<? extends AbstractMetaDataLoader<?>> getLoaderForClass(Class<?> metaDataClass)
{
return registeredLoaders.get(metaDataClass);
}
/***************************************************************************
**
***************************************************************************/
public static boolean hasLoaderForSimpleName(String targetSimpleName)
{
return registeredLoadersByTargetSimpleName.containsKey(targetSimpleName);
}
/***************************************************************************
**
***************************************************************************/
public static Class<? extends AbstractMetaDataLoader<?>> getLoaderForSimpleName(String targetSimpleName)
{
return registeredLoadersByTargetSimpleName.get(targetSimpleName);
}
}

View File

@ -0,0 +1,70 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2024. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.kingsrook.qqq.backend.core.instances.loaders.implementations;
import java.util.Map;
import com.kingsrook.qqq.backend.core.instances.loaders.AbstractMetaDataLoader;
import com.kingsrook.qqq.backend.core.instances.loaders.QMetaDataLoaderException;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject;
/*******************************************************************************
**
*******************************************************************************/
public class GenericMetaDataLoader<T extends QMetaDataObject> extends AbstractMetaDataLoader<T>
{
private final Class<T> metaDataClass;
/*******************************************************************************
** Constructor
**
*******************************************************************************/
public GenericMetaDataLoader(Class<T> metaDataClass)
{
this.metaDataClass = metaDataClass;
}
/***************************************************************************
**
***************************************************************************/
@Override
public T mapToMetaDataObject(QInstance qInstance, Map<String, Object> map) throws QMetaDataLoaderException
{
try
{
T object = metaDataClass.getConstructor().newInstance();
reflectivelyMap(qInstance, object, map);
return (object);
}
catch(Exception e)
{
throw (new QMetaDataLoaderException("Error loading metaData object of type " + metaDataClass.getSimpleName(), e));
}
}
}

View File

@ -26,6 +26,7 @@ import java.nio.charset.StandardCharsets;
import com.kingsrook.qqq.backend.core.BaseTest; import com.kingsrook.qqq.backend.core.BaseTest;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance; import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject; import com.kingsrook.qqq.backend.core.model.metadata.QMetaDataObject;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -50,11 +51,33 @@ class ClassDetectingMetaDataLoaderTest extends BaseTest
class: QTableMetaData class: QTableMetaData
version: 1 version: 1
name: myTable name: myTable
backendName: someBackend
""", StandardCharsets.UTF_8), "myTable.yaml"); """, StandardCharsets.UTF_8), "myTable.yaml");
assertThat(qMetaDataObject).isInstanceOf(QTableMetaData.class); assertThat(qMetaDataObject).isInstanceOf(QTableMetaData.class);
QTableMetaData qTableMetaData = (QTableMetaData) qMetaDataObject; QTableMetaData qTableMetaData = (QTableMetaData) qMetaDataObject;
assertEquals("myTable", qTableMetaData.getName()); assertEquals("myTable", qTableMetaData.getName());
assertEquals("someBackend", qTableMetaData.getBackendName());
}
/*******************************************************************************
**
*******************************************************************************/
@Test
void testProcess() throws QMetaDataLoaderException
{
QMetaDataObject qMetaDataObject = new ClassDetectingMetaDataLoader().fileToMetaDataObject(new QInstance(), IOUtils.toInputStream("""
class: QProcessMetaData
version: 1
name: myProcess
tableName: someTable
""", StandardCharsets.UTF_8), "myProcess.yaml");
assertThat(qMetaDataObject).isInstanceOf(QProcessMetaData.class);
QProcessMetaData qProcessMetaData = (QProcessMetaData) qMetaDataObject;
assertEquals("myProcess", qProcessMetaData.getName());
assertEquals("someTable", qProcessMetaData.getTableName());
} }

View File

@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.instances.loaders;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.Set;
import com.kingsrook.qqq.backend.core.BaseTest; import com.kingsrook.qqq.backend.core.BaseTest;
import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers; import com.kingsrook.qqq.backend.core.actions.customizers.TableCustomizers;
import com.kingsrook.qqq.backend.core.context.QContext; import com.kingsrook.qqq.backend.core.context.QContext;
@ -33,6 +34,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeType;
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType; import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
import com.kingsrook.qqq.backend.core.model.metadata.permissions.DenyBehavior; import com.kingsrook.qqq.backend.core.model.metadata.permissions.DenyBehavior;
import com.kingsrook.qqq.backend.core.model.metadata.permissions.PermissionLevel; import com.kingsrook.qqq.backend.core.model.metadata.permissions.PermissionLevel;
import com.kingsrook.qqq.backend.core.model.metadata.tables.Capability;
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
import com.kingsrook.qqq.backend.core.utils.TestUtils; import com.kingsrook.qqq.backend.core.utils.TestUtils;
import com.kingsrook.qqq.backend.core.utils.YamlUtils; import com.kingsrook.qqq.backend.core.utils.YamlUtils;
@ -113,6 +115,9 @@ class QTableMetaDataLoaderTest extends BaseTest
preDeleteRecord: preDeleteRecord:
name: com.kingsrook.SomePreDelete name: com.kingsrook.SomePreDelete
codeType: JAVA codeType: JAVA
disabledCapabilities:
- TABLE_COUNT
- QUERY_STATS
""", StandardCharsets.UTF_8), "myTable.yaml"); """, StandardCharsets.UTF_8), "myTable.yaml");
assertEquals("myTable", table.getName()); assertEquals("myTable", table.getName());
@ -145,6 +150,8 @@ class QTableMetaDataLoaderTest extends BaseTest
assertEquals(2, table.getCustomizers().size()); assertEquals(2, table.getCustomizers().size());
assertEquals("com.kingsrook.SomePostQuery", table.getCustomizers().get(TableCustomizers.POST_QUERY_RECORD.getRole()).getName()); assertEquals("com.kingsrook.SomePostQuery", table.getCustomizers().get(TableCustomizers.POST_QUERY_RECORD.getRole()).getName());
assertEquals("com.kingsrook.SomePreDelete", table.getCustomizers().get(TableCustomizers.PRE_DELETE_RECORD.getRole()).getName()); assertEquals("com.kingsrook.SomePreDelete", table.getCustomizers().get(TableCustomizers.PRE_DELETE_RECORD.getRole()).getName());
assertEquals(Set.of(Capability.TABLE_COUNT, Capability.QUERY_STATS), table.getDisabledCapabilities());
} }

View File

@ -0,0 +1,59 @@
package com.kingsrook.qqq.backend.core.instances.loaders.implementations;
import java.nio.charset.StandardCharsets;
import com.kingsrook.qqq.backend.core.BaseTest;
import com.kingsrook.qqq.backend.core.instances.loaders.QMetaDataLoaderException;
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/*******************************************************************************
** Unit test for GenericMetaDataLoader - providing coverage for AbstractMetaDataLoader.
*******************************************************************************/
class GenericMetaDataLoaderTest extends BaseTest
{
/*******************************************************************************
**
*******************************************************************************/
@Test
void testProcess() throws QMetaDataLoaderException
{
////////////////////////////////////////////////////////////////////////////////
// trying to get some coverage of various types in here (for Abstract loader) //
////////////////////////////////////////////////////////////////////////////////
QProcessMetaData process = new GenericMetaDataLoader<>(QProcessMetaData.class).fileToMetaDataObject(new QInstance(), IOUtils.toInputStream("""
class: QProcessMetaData
version: 1
name: myProcess
tableName: someTable
maxInputRecords: 1
isHidden: true
""", StandardCharsets.UTF_8), "myProcess.yaml");
assertEquals("myProcess", process.getName());
assertEquals("someTable", process.getTableName());
assertEquals(1, process.getMaxInputRecords());
assertTrue(process.getIsHidden());
}
/*******************************************************************************
** just here for coverage of this class, as we're failing to hit it otherwise.
*******************************************************************************/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
void testNoValueException()
{
assertThatThrownBy(() -> new GenericMetaDataLoader(QBackendMetaData.class).reflectivelyMapValue(new QInstance(), null, GenericMetaDataLoaderTest.class, "rawValue"));
}
}