Comments :)

This commit is contained in:
Darin Kelkhoff
2021-12-01 21:51:15 -06:00
parent 2388534c0c
commit 3a03e04706
72 changed files with 238 additions and 33 deletions

View File

@ -10,6 +10,7 @@ import com.kingsrook.qqq.backend.core.modules.interfaces.QModuleInterface;
/*******************************************************************************
** Action to delete 1 or more records.
**
*******************************************************************************/
public class DeleteAction

View File

@ -10,6 +10,7 @@ import com.kingsrook.qqq.backend.core.modules.interfaces.QModuleInterface;
/*******************************************************************************
** Action to insert one or more records.
**
*******************************************************************************/
public class InsertAction

View File

@ -11,6 +11,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMeta
/*******************************************************************************
** Action to fetch top-level meta-data in a qqq instance.
**
*******************************************************************************/
public class MetaDataAction

View File

@ -10,6 +10,7 @@ import com.kingsrook.qqq.backend.core.modules.interfaces.QModuleInterface;
/*******************************************************************************
** Action to run a query against a table.
**
*******************************************************************************/
public class QueryAction

View File

@ -10,6 +10,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMeta
/*******************************************************************************
** Action to fetch meta-data for a table.
**
*******************************************************************************/
public class TableMetaDataAction

View File

@ -18,13 +18,17 @@ import org.apache.commons.csv.CSVRecord;
/*******************************************************************************
** Adapter class to convert a CSV string into a list of QRecords.
**
*******************************************************************************/
public class CsvToQRecordAdapter
{
/*******************************************************************************
** todo - meta-data validation, mapping, type handling
** convert a CSV String into a List of QRecords, for a given table, optionally
** using a given mapping.
**
** todo - meta-data validation, type handling
*******************************************************************************/
public List<QRecord> buildRecordsFromCsv(String csv, QTableMetaData table, AbstractQFieldMapping<?> mapping)
{

View File

@ -11,12 +11,17 @@ import org.json.JSONObject;
/*******************************************************************************
** Adapter class to convert a JSON string into a QFieldMapping object
**
*******************************************************************************/
public class JsonToQFieldMappingAdapter
{
/*******************************************************************************
** adapts a json string into an AbstractQFieldMapping.
**
** The mapping will be a QKeyBasedFieldMapping if the keys in the json object are
** Strings. It will be a QIndexBasedFieldMapping if the keys are integers.
**
*******************************************************************************/
public AbstractQFieldMapping<?> buildMappingFromJson(String json)

View File

@ -15,13 +15,17 @@ import org.json.JSONObject;
/*******************************************************************************
** Adapter class to convert a JSON string into a list of QRecords.
**
*******************************************************************************/
public class JsonToQRecordAdapter
{
/*******************************************************************************
** todo - meta-data validation, mapping, type handling
** convert a JSON String into a List of QRecords, for a given table, optionally
** using a given mapping.
**
** todo - meta-data validation, use the mapping, type handling
*******************************************************************************/
public List<QRecord> buildRecordsFromJson(String json, QTableMetaData table, AbstractQFieldMapping<?> mapping)
{
@ -69,6 +73,8 @@ public class JsonToQRecordAdapter
/*******************************************************************************
** private method to build one QRecord from one jsonObject
**
** todo - meta-data validation, mapping, type handling
*******************************************************************************/
private QRecord buildRecordFromJsonObject(JSONObject jsonObject)

View File

@ -7,7 +7,9 @@ package com.kingsrook.qqq.backend.core.exceptions;
*******************************************************************************/
public class QException extends Exception
{
/*******************************************************************************
** Constructor of message
**
*******************************************************************************/
public QException(String message)
@ -18,6 +20,7 @@ public class QException extends Exception
/*******************************************************************************
** Constructor of message & cause
**
*******************************************************************************/
public QException(String message, Throwable cause)

View File

@ -7,6 +7,8 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
/*******************************************************************************
** Exception thrown during qqq-starup, if a QInstance is found to have validation
** issues. Contains a list of reasons (to avoid spoon-feeding as much as possible).
**
*******************************************************************************/
public class QInstanceValidationException extends QException
@ -16,6 +18,7 @@ public class QInstanceValidationException extends QException
/*******************************************************************************
** Constructor of message - does not populate reasons!
**
*******************************************************************************/
public QInstanceValidationException(String message)
@ -26,6 +29,7 @@ public class QInstanceValidationException extends QException
/*******************************************************************************
** Constructor of a list of reasons. They feed into the core exception message.
**
*******************************************************************************/
public QInstanceValidationException(List<String> reasons)
@ -44,6 +48,7 @@ public class QInstanceValidationException extends QException
/*******************************************************************************
** Constructor of an array/varargs of reasons. They feed into the core exception message.
**
*******************************************************************************/
public QInstanceValidationException(String... reasons)
@ -62,6 +67,7 @@ public class QInstanceValidationException extends QException
/*******************************************************************************
** Constructor of message & cause - does not populate reasons!
**
*******************************************************************************/
public QInstanceValidationException(String message, Throwable cause)

View File

@ -2,12 +2,14 @@ package com.kingsrook.qqq.backend.core.exceptions;
/*******************************************************************************
* Base class for checked exceptions thrown in qqq.
* Exception thrown while doing module-dispatch
*
*******************************************************************************/
public class QModuleDispatchException extends QException
{
/*******************************************************************************
** Constructor of message
**
*******************************************************************************/
public QModuleDispatchException(String message)
@ -18,6 +20,7 @@ public class QModuleDispatchException extends QException
/*******************************************************************************
** Constructor of message & cause
**
*******************************************************************************/
public QModuleDispatchException(String message, Throwable cause)

View File

@ -2,6 +2,7 @@ package com.kingsrook.qqq.backend.core.exceptions;
/*******************************************************************************
** Exception with a good-quality message meant to be shown to an end-user.
**
*******************************************************************************/
public class QUserFacingException extends QException
@ -9,6 +10,7 @@ public class QUserFacingException extends QException
/*******************************************************************************
** Constructor of message
**
*******************************************************************************/
public QUserFacingException(String message)
@ -19,6 +21,7 @@ public class QUserFacingException extends QException
/*******************************************************************************
** Constructor of message & cause
**
*******************************************************************************/
public QUserFacingException(String message, Throwable cause)

View File

@ -9,6 +9,8 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
/*******************************************************************************
** As part of helping a QInstance be created and/or validated, apply some default
** transfomations to it, such as populating missing labels based on names.
**
*******************************************************************************/
public class QInstanceEnricher

View File

@ -2,6 +2,7 @@ package com.kingsrook.qqq.backend.core.instances;
/*******************************************************************************
** Object used to mark a QInstance has having been validated.
**
*******************************************************************************/
public final class QInstanceValidationKey
@ -10,6 +11,7 @@ public final class QInstanceValidationKey
** package-private constructor, so that only this package can create an instance
** of this class, but an instance of this class is required to mark an instance
** as validated, so no one can cheat.
**
*******************************************************************************/
QInstanceValidationKey()
{

View File

@ -11,6 +11,13 @@ import com.kingsrook.qqq.backend.core.utils.StringUtils;
/*******************************************************************************
** Class that knows how to take a look at the data in a QInstance, and report
** if it is all valid - e.g., non-null things are set; references line-up (e.g.,
** a table's backend must be a defined backend).
**
** Prior to doing validation, the the QInstanceEnricher is ran over the QInstance,
** e.g., to fill in things that can be defaulted or assumed. TODO let the instance
** customize or opt-out of Enrichment.
**
*******************************************************************************/
public class QInstanceValidator
@ -34,6 +41,7 @@ public class QInstanceValidator
/////////////////////////////////////////////////////////////////////////////////////////////////
// before validation, enrich the object (e.g., to fill in values that the user doesn't have to //
/////////////////////////////////////////////////////////////////////////////////////////////////
// TODO - possible point of customization (use a different enricher, or none, or pass it options).
new QInstanceEnricher().enrich(qInstance);
}
catch(Exception e)

View File

@ -10,6 +10,7 @@ public abstract class AbstractQFieldMapping<T>
/*******************************************************************************
** Enum to define the types of sources a mapping may use
**
*******************************************************************************/
@SuppressWarnings("rawtypes")
public enum SourceType
@ -46,12 +47,14 @@ public abstract class AbstractQFieldMapping<T>
/*******************************************************************************
** For a given field, return its source - a key (e.g., from a json object or csv
** with a header row) or an index (for a csv w/o a header)
**
*******************************************************************************/
public abstract T getFieldSource(String fieldName);
/*******************************************************************************
** for a mapping instance, get what its source-type is
**
*******************************************************************************/
public abstract SourceType getSourceType();
}

View File

@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
/*******************************************************************************
** Base request class for all Q actions.
**
*******************************************************************************/
public abstract class AbstractQRequest

View File

@ -2,6 +2,7 @@ package com.kingsrook.qqq.backend.core.model.actions;
/*******************************************************************************
** Abstract base class for any qqq-action's result.
**
*******************************************************************************/
public abstract class AbstractQResult

View File

@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
/*******************************************************************************
** Base class for any qqq action that works against a table.
**
*******************************************************************************/
public abstract class AbstractQTableRequest extends AbstractQRequest

View File

@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
/*******************************************************************************
** Request for a Delete action.
**
*******************************************************************************/
public class DeleteRequest extends AbstractQTableRequest

View File

@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
/*******************************************************************************
** Request data handler for the Insert action
**
*******************************************************************************/
public class InsertRequest extends AbstractQTableRequest

View File

@ -6,7 +6,7 @@ import com.kingsrook.qqq.backend.core.model.data.QRecordWithStatus;
/*******************************************************************************
* Result for a query action
* Result for an insert action
*
*******************************************************************************/
public class InsertResult extends AbstractQResult

View File

@ -5,6 +5,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
/*******************************************************************************
** Request for the meta-data action
**
*******************************************************************************/
public class MetaDataRequest extends AbstractQRequest

View File

@ -2,6 +2,7 @@ package com.kingsrook.qqq.backend.core.model.actions;
/*******************************************************************************
** Possible query criteria field operators
**
*******************************************************************************/
public enum QCriteriaOperator

View File

@ -6,7 +6,7 @@ import java.util.List;
/*******************************************************************************
* Component of a Query
* A single criteria Component of a Query
*
*******************************************************************************/
public class QFilterCriteria

View File

@ -2,6 +2,7 @@ package com.kingsrook.qqq.backend.core.model.actions;
/*******************************************************************************
** Bean representing an element of a query order-by clause.
**
*******************************************************************************/
public class QFilterOrderBy

View File

@ -6,7 +6,11 @@ import java.util.Map;
/*******************************************************************************
** Note; 1-based index!!
** Field Mapping implementation that uses Integer keys (e.g., from a CSV file
** WITHOUT a header row).
**
** Note: 1-based index!!
**
*******************************************************************************/
public class QIndexBasedFieldMapping extends AbstractQFieldMapping<Integer>
{
@ -15,6 +19,8 @@ public class QIndexBasedFieldMapping extends AbstractQFieldMapping<Integer>
/*******************************************************************************
** Get the field source (e.g., integer index of a CSV column) corresponding to a
** propery qqq table fieldName.
**
*******************************************************************************/
@Override
@ -31,6 +37,7 @@ public class QIndexBasedFieldMapping extends AbstractQFieldMapping<Integer>
/*******************************************************************************
** Tell framework what kind of keys this mapping class uses (INDEX)
**
*******************************************************************************/
@Override
@ -42,6 +49,8 @@ public class QIndexBasedFieldMapping extends AbstractQFieldMapping<Integer>
/*******************************************************************************
** Add a single mapping to this mapping object. fieldName = qqq metaData fieldName,
** key = field index (integer) in the CSV
**
*******************************************************************************/
public void addMapping(String fieldName, Integer key)
@ -56,6 +65,8 @@ public class QIndexBasedFieldMapping extends AbstractQFieldMapping<Integer>
/*******************************************************************************
** Fluently add a single mapping to this mapping object. fieldName = qqq metaData
** fieldName, key = field index (integer) in the CSV
**
*******************************************************************************/
public QIndexBasedFieldMapping withMapping(String fieldName, Integer key)

View File

@ -6,6 +6,8 @@ import java.util.Map;
/*******************************************************************************
** Field Mapping implementation that uses string keys (e.g., from a CSV file
** with a header row, or from one JSON object to the proper qqq field names)
**
*******************************************************************************/
public class QKeyBasedFieldMapping extends AbstractQFieldMapping<String>
@ -15,6 +17,8 @@ public class QKeyBasedFieldMapping extends AbstractQFieldMapping<String>
/*******************************************************************************
** Get the source field (e.g., name that's in the CSV header or the input json
** object) corresponding to a propery qqq table fieldName.
**
*******************************************************************************/
@Override
@ -31,6 +35,7 @@ public class QKeyBasedFieldMapping extends AbstractQFieldMapping<String>
/*******************************************************************************
** Tell framework what kind of keys this mapping class uses (KEY)
**
*******************************************************************************/
@Override
@ -42,6 +47,8 @@ public class QKeyBasedFieldMapping extends AbstractQFieldMapping<String>
/*******************************************************************************
** Add a single mapping to this mapping object. fieldName = qqq metaData fieldName,
** key = field name in the CSV or source-json, for example.
**
*******************************************************************************/
public void addMapping(String fieldName, String key)
@ -56,6 +63,8 @@ public class QKeyBasedFieldMapping extends AbstractQFieldMapping<String>
/*******************************************************************************
** Fluently add a single mapping to this mapping object. fieldName = qqq metaData fieldName,
** key = field name in the CSV or source-json, for example.
**
*******************************************************************************/
public QKeyBasedFieldMapping withMapping(String fieldName, String key)

View File

@ -5,6 +5,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
/*******************************************************************************
** Request data for the Query action
**
*******************************************************************************/
public class QueryRequest extends AbstractQTableRequest

View File

@ -6,8 +6,8 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
/*******************************************************************************
* Result for a query action
*
** Result for a query action
**
*******************************************************************************/
public class QueryResult extends AbstractQResult
{

View File

@ -5,6 +5,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
/*******************************************************************************
** Request for meta-data for a table.
**
*******************************************************************************/
public class TableMetaDataRequest extends AbstractQRequest

View File

@ -5,7 +5,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.frontend.QFrontendTableMeta
/*******************************************************************************
* Result for a metaData action
* Result for a table-metaData action
*
*******************************************************************************/
public class TableMetaDataResult extends AbstractQResult

View File

@ -7,7 +7,7 @@ import java.util.Map;
/*******************************************************************************
* Data Record within qqq
* Data Record within qqq. e.g., a single row from a database.
*
*******************************************************************************/
public class QRecord

View File

@ -5,6 +5,10 @@ import java.util.List;
/*******************************************************************************
** Wrapper on a QRecord, to add status information after an action took place.
** e.g., any errors that occurred.
**
** TODO - expand?
**
*******************************************************************************/
public class QRecordWithStatus extends QRecord

View File

@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonFilter;
/*******************************************************************************
** Meta-data to provide details of a backend (e.g., RDBMS instance, S3 buckets,
** NoSQL table, etc) within a qqq instance
**
*******************************************************************************/
public class QBackendMetaData

View File

@ -2,6 +2,7 @@ package com.kingsrook.qqq.backend.core.model.metadata;
/*******************************************************************************
** Meta-data to represent a single field in a table.
**
*******************************************************************************/
public class QFieldMetaData

View File

@ -2,6 +2,7 @@ package com.kingsrook.qqq.backend.core.model.metadata;
/*******************************************************************************
** Possible data types for Q-fields.
**
*******************************************************************************/
public enum QFieldType

View File

@ -8,6 +8,7 @@ import com.kingsrook.qqq.backend.core.instances.QInstanceValidationKey;
/*******************************************************************************
** Container for all meta-data in a running instance of a QQQ application.
**
*******************************************************************************/
public class QInstance

View File

@ -6,6 +6,7 @@ import java.util.Map;
/*******************************************************************************
** Meta-Data to define a table in a QQQ instance.
**
*******************************************************************************/
public class QTableMetaData

View File

@ -8,8 +8,9 @@ import com.kingsrook.qqq.backend.core.model.metadata.QFieldType;
/*******************************************************************************
* Version of QTableMetaData that's meant for transmitting to a frontend.
* Version of QFieldMetaData that's meant for transmitting to a frontend.
* e.g., it excludes backend-only details.
*
*******************************************************************************/
@JsonInclude(Include.NON_NULL)
public class QFrontendFieldMetaData

View File

@ -12,6 +12,7 @@ import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
/*******************************************************************************
* Version of QTableMetaData that's meant for transmitting to a frontend.
* e.g., it excludes backend-only details.
*
*******************************************************************************/
@JsonInclude(Include.NON_NULL)
public class QFrontendTableMetaData
@ -89,4 +90,4 @@ public class QFrontendTableMetaData
{
return fields;
}
}
}

View File

@ -9,6 +9,10 @@ import com.kingsrook.qqq.backend.core.modules.interfaces.QModuleInterface;
/*******************************************************************************
** This class is responsible for loading a backend module, by its name, and
** returning an instance.
**
** TODO - make this mapping runtime-bound, not pre-compiled in.
**
*******************************************************************************/
public class QModuleDispatcher

View File

@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.model.actions.DeleteResult;
/*******************************************************************************
** Interface for the Delete action.
**
*******************************************************************************/
public interface DeleteInterface

View File

@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.model.actions.InsertResult;
/*******************************************************************************
** Interface for the Insert action.
**
*******************************************************************************/
public interface InsertInterface

View File

@ -2,6 +2,10 @@ package com.kingsrook.qqq.backend.core.modules.interfaces;
/*******************************************************************************
** Interface that a QModule must implement.
**
** Note, methods all have a default version, which throws a 'not implement'
** exception.
**
*******************************************************************************/
public interface QModuleInterface

View File

@ -7,6 +7,7 @@ import com.kingsrook.qqq.backend.core.model.actions.QueryResult;
/*******************************************************************************
** Interface for the Query action.
**
*******************************************************************************/
public interface QueryInterface

View File

@ -10,6 +10,7 @@ import com.kingsrook.qqq.backend.core.modules.interfaces.DeleteInterface;
/*******************************************************************************
** Mocked up version of delete action.
**
*******************************************************************************/
public class MockDeleteAction implements DeleteInterface

View File

@ -9,6 +9,7 @@ import com.kingsrook.qqq.backend.core.modules.interfaces.InsertInterface;
/*******************************************************************************
** Mocked up version of insert action.
**
*******************************************************************************/
public class MockInsertAction implements InsertInterface

View File

@ -8,6 +8,10 @@ import com.kingsrook.qqq.backend.core.modules.interfaces.QueryInterface;
/*******************************************************************************
** A Mock implementation of the QModuleInterface.
**
** Mostly just exists to allow the backend-core repository to be able to run
** tests over all the actions available through the QModuleInterface.
**
*******************************************************************************/
public class MockModule implements QModuleInterface

View File

@ -12,6 +12,7 @@ import com.kingsrook.qqq.backend.core.modules.interfaces.QueryInterface;
/*******************************************************************************
** Mocked up version of query action.
**
*******************************************************************************/
public class MockQueryAction implements QueryInterface

View File

@ -10,6 +10,7 @@ import java.util.function.Function;
/*******************************************************************************
** Utility class for working with Collections.
**
*******************************************************************************/
public class CollectionUtils
@ -101,6 +102,7 @@ public class CollectionUtils
/*******************************************************************************
** add all values from one map to another.
**
*******************************************************************************/
public static <K, V> void addAllToMap(Map<K, V> addingTo, Map<K, V> addingFrom)
@ -114,6 +116,8 @@ public class CollectionUtils
/*******************************************************************************
** Build a map from a list, supplying a function that extracts keys from the
** objects in the list (the objects in the list become the values in the map).
**
*******************************************************************************/
public static <K, V> Map<K, V> listToMap(List<V> values, Function<V, ? extends K> keyFunction)
@ -135,6 +139,9 @@ public class CollectionUtils
/*******************************************************************************
** Build a map from a list, supplying a function that extracts keys from the
** objects in the list, and another function that extracts the values from the
** objects in the list.
**
*******************************************************************************/
public static <E, K, V> Map<K, V> listToMap(List<E> elements, Function<E, ? extends K> keyFunction, Function<E, ? extends V> valueFunction)
@ -156,6 +163,8 @@ public class CollectionUtils
/*******************************************************************************
** Build a listingHash from a list, supplying a function that extracts keys from the
** objects in the list (the objects in the list become the values in the map).
**
*******************************************************************************/
public static <K, V> ListingHash<K, V> listToListingHash(List<V> values, Function<V, ? extends K> keyFunction)
@ -218,6 +227,9 @@ public class CollectionUtils
/*******************************************************************************
** Convert a list to a 2-level Map (ie., Map of Map of Key,Value), where 2
** lambdas are provided for extract the two levels of keys from the objects in
** the list, and the values in the map are the values in the list.
**
*******************************************************************************/
public static <K1, K2, V> Map<K1, Map<K2, V>> listTo2LevelMap(List<V> values, Function<V, ? extends K1> keyFunction1, Function<V, ? extends K2> keyFunction2)
@ -279,6 +291,8 @@ public class CollectionUtils
/*******************************************************************************
** build comma-delimited string of question marks from a collection (e.g., for
** an sql string)
**
*******************************************************************************/
public static String getQuestionMarks(Collection<?> c)

View File

@ -2,12 +2,15 @@ package com.kingsrook.qqq.backend.core.utils;
/*******************************************************************************
** Utility class for working with exceptions.
**
*******************************************************************************/
public class ExceptionUtils
{
/*******************************************************************************
** Find a specific exception class in an exception's caused-by chain. Returns
** null if not found. Be aware, checks for class.equals -- not instanceof.
**
*******************************************************************************/
public static <T extends Throwable> T findClassInRootChain(Throwable e, Class<T> targetClass)

View File

@ -15,6 +15,8 @@ import org.json.JSONObject;
/*******************************************************************************
** Utility class for working with JSON.
**
** See: https://www.baeldung.com/jackson-vs-gson
**
*******************************************************************************/
@ -25,6 +27,9 @@ public class JsonUtils
/*******************************************************************************
** Serialize any object into a JSON String.
**
** Internally using jackson - so jackson annotations apply!
**
*******************************************************************************/
public static String toJson(Object object)
@ -45,6 +50,9 @@ public class JsonUtils
/*******************************************************************************
** Serialize any object into a "pretty" / formatted JSON String.
**
** Internally using jackson - so jackson annotations apply!
**
*******************************************************************************/
public static String toPrettyJson(Object object)
@ -65,6 +73,9 @@ public class JsonUtils
/*******************************************************************************
** De-serialize a json string into an object of the specified class.
**
** Internally using jackson - so jackson annotations apply!
**
*******************************************************************************/
public static <T> T toObject(String json, Class<T> targetClass) throws IOException
@ -77,6 +88,7 @@ public class JsonUtils
/*******************************************************************************
** De-serialize a json string into a JSONObject (string must start with "{")
**
*******************************************************************************/
public static JSONObject toJSONObject(String json) throws JSONException
@ -88,6 +100,7 @@ public class JsonUtils
/*******************************************************************************
** De-serialize a json string into a JSONArray (string must start with "[")
**
*******************************************************************************/
public static JSONArray toJSONArray(String json) throws JSONException
@ -99,6 +112,7 @@ public class JsonUtils
/*******************************************************************************
** Standard private method to build jackson ObjectMapper with standard features.
**
*******************************************************************************/
private static ObjectMapper newObjectMapper()
@ -121,6 +135,8 @@ public class JsonUtils
/*******************************************************************************
** Check if a string looks like it could be a JSON object (e.g., starts with "{"
** (plus optional whitespace))
**
*******************************************************************************/
public static boolean looksLikeObject(String json)
@ -131,6 +147,8 @@ public class JsonUtils
/*******************************************************************************
** Check if a string looks like it could be a JSON array (e.g., starts with "["
** (plus optional whitespace))
**
*******************************************************************************/
public static boolean looksLikeArray(String json)

View File

@ -82,6 +82,9 @@ public class ListingHash<K, V> implements Map<K, List<V>>, Serializable
/*******************************************************************************
** Add all object from another ListingHash ('that') to this one. Note, does it
** at the level of the whole key=list (e.g., if a key was already in this, it'll
** be replaced with the list from 'that'.
**
*******************************************************************************/
public void addAll(ListingHash<K, V> that)

View File

@ -8,6 +8,7 @@ import java.util.regex.Pattern;
/*******************************************************************************
** Utility methods for working with Strings
**
*******************************************************************************/
public class StringUtils
@ -111,8 +112,8 @@ public class StringUtils
/*******************************************************************************
* truncate a string (null safely) at a max length.
*
** truncate a string (null- and index-bounds- safely) at a max length.
**
*******************************************************************************/
public static String safeTruncate(String input, int maxLength)
{
@ -132,7 +133,10 @@ public class StringUtils
/*******************************************************************************
*
** null- and index-bounds- safely truncate a string to a max length, appending
** a suffix (like "...") if it did get truncated. Note that the returned string,
** with the suffix added, will be at most maxLength.
**
*******************************************************************************/
public static String safeTruncate(String input, int maxLength, String suffix)
{
@ -289,6 +293,8 @@ public class StringUtils
/*******************************************************************************
** Switch between strings based on if the size of the parameter collection. If
** it is 1 (the singular) or not-1 (0 or 2+, the plural). Get back "" or "s"
**
*******************************************************************************/
public static String plural(Collection<?> collection)
@ -299,6 +305,8 @@ public class StringUtils
/*******************************************************************************
** Switch between strings based on if the 'size' parameter is 1 (the singular)
** or not-1 (0 or 2+, the plural). Get back "" or "s"
**
*******************************************************************************/
public static String plural(Integer size)
@ -309,6 +317,9 @@ public class StringUtils
/*******************************************************************************
** Switch between strings based on if the size of the parameter collection. If
** it is 1 (the singular) or not-1 (0 or 2+, the plural). Specify/customize the
** values that you get back (e.g., "y", "ies")
**
*******************************************************************************/
public static String plural(Collection<?> collection, String ifOne, String ifNotOne)
@ -319,6 +330,9 @@ public class StringUtils
/*******************************************************************************
** Switch between strings based on if the 'size' parameter is 1 (the singular)
** or not-1 (0 or 2+, the plural). Specify/customize the values that you get back
** (e.g., "y", "ies")
**
*******************************************************************************/
public static String plural(Integer size, String ifOne, String ifNotOne)

View File

@ -13,12 +13,15 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
/*******************************************************************************
** Unit test for DeleteAction
**
*******************************************************************************/
class DeleteActionTest
{
/*******************************************************************************
** At the core level, there isn't much that can be asserted, as it uses the
** mock implementation - just confirming that all of the "wiring" works.
**
*******************************************************************************/
@Test
@ -33,4 +36,4 @@ class DeleteActionTest
assertTrue(result.getRecords().stream().allMatch(r -> r.getErrors() == null));
}
}
}

View File

@ -13,12 +13,15 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
/*******************************************************************************
** Unit test for InsertAction
**
*******************************************************************************/
class InsertActionTest
{
/*******************************************************************************
** At the core level, there isn't much that can be asserted, as it uses the
** mock implementation - just confirming that all of the "wiring" works.
**
*******************************************************************************/
@Test
@ -35,4 +38,4 @@ class InsertActionTest
assertNotNull(result);
}
}
}

View File

@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.*;
/*******************************************************************************
** Unit test for MetaDataAction
**
*******************************************************************************/
class MetaDataActionTest
@ -29,4 +30,4 @@ class MetaDataActionTest
assertEquals("person", result.getTables().get("person").getName());
assertEquals("Person", result.getTables().get("person").getLabel());
}
}
}

View File

@ -10,12 +10,15 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
/*******************************************************************************
** Unit test for QueryAction
**
*******************************************************************************/
class QueryActionTest
{
/*******************************************************************************
** At the core level, there isn't much that can be asserted, as it uses the
** mock implementation - just confirming that all of the "wiring" works.
**
*******************************************************************************/
@Test
@ -26,4 +29,4 @@ class QueryActionTest
QueryResult result = new QueryAction().execute(request);
assertNotNull(result);
}
}
}

View File

@ -13,12 +13,14 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
/*******************************************************************************
** Unit test for TableMetaDataAction
**
*******************************************************************************/
class TableMetaDataActionTest
{
/*******************************************************************************
** Test basic success case.
**
*******************************************************************************/
@Test
@ -36,6 +38,7 @@ class TableMetaDataActionTest
/*******************************************************************************
** Test exeption is thrown for the "not-found" case.
**
*******************************************************************************/
@Test
@ -48,4 +51,4 @@ class TableMetaDataActionTest
});
}
}
}

View File

@ -14,6 +14,7 @@ import static org.junit.jupiter.api.Assertions.fail;
/*******************************************************************************
** Unit test for CsvToQRecordAdapter
**
*******************************************************************************/
class CsvToQRecordAdapterTest
@ -219,4 +220,4 @@ class CsvToQRecordAdapterTest
}
}
}

View File

@ -11,6 +11,7 @@ import static org.junit.jupiter.api.Assertions.fail;
/*******************************************************************************
** Unit test for JsonToQFieldMappingAdapter
**
*******************************************************************************/
class JsonToQFieldMappingAdapterTest
@ -149,4 +150,4 @@ class JsonToQFieldMappingAdapterTest
fail("Didn't throw expected exception");
}
}
}

View File

@ -9,6 +9,7 @@ import static org.junit.jupiter.api.Assertions.*;
/*******************************************************************************
** Unit test for JsonToQRecordAdapter
**
*******************************************************************************/
class JsonToQRecordAdapterTest
@ -147,4 +148,4 @@ class JsonToQRecordAdapterTest
testExpectedToThrow("[ 1701 ]");
}
}
}

View File

@ -11,12 +11,14 @@ import static org.junit.jupiter.api.Assertions.assertNull;
/*******************************************************************************
** Unit test for QInstanceEnricher
**
*******************************************************************************/
class QInstanceEnricherTest
{
/*******************************************************************************
** Test that a table missing a label gets the default label applied (name w/ UC-first).
**
*******************************************************************************/
@Test
@ -32,6 +34,8 @@ class QInstanceEnricherTest
/*******************************************************************************
** Test that a table missing a label and a name doesn't NPE, but just keeps
** the name & label both null.
**
*******************************************************************************/
@Test
@ -50,6 +54,7 @@ class QInstanceEnricherTest
/*******************************************************************************
** Test that a field missing a label gets the default label applied (name w/ UC-first)
**
*******************************************************************************/
@Test
@ -63,4 +68,4 @@ class QInstanceEnricherTest
assertEquals("Id", idField.getLabel());
}
}
}

View File

@ -12,12 +12,14 @@ import static org.junit.jupiter.api.Assertions.fail;
/*******************************************************************************
** Unit test for QInstanceValidator.
**
*******************************************************************************/
class QInstanceValidatorTest
{
/*******************************************************************************
** Test a valid instance - should just pass
**
*******************************************************************************/
@Test
@ -29,6 +31,7 @@ class QInstanceValidatorTest
/*******************************************************************************
** Test an instane with null backends - should throw.
**
*******************************************************************************/
@Test
@ -50,6 +53,7 @@ class QInstanceValidatorTest
/*******************************************************************************
** Test an instane with empty map of backends - should throw.
**
*******************************************************************************/
@Test
@ -71,6 +75,7 @@ class QInstanceValidatorTest
/*******************************************************************************
** Test an instane with null tables - should throw.
**
*******************************************************************************/
@Test
@ -92,6 +97,7 @@ class QInstanceValidatorTest
/*******************************************************************************
** Test an instane with empty map of tables - should throw.
**
*******************************************************************************/
@Test
@ -113,6 +119,8 @@ class QInstanceValidatorTest
/*******************************************************************************
** Test an instane where a table and a backend each have a name attribute that
** doesn't match the key that those objects have in the instance's maps - should throw.
**
*******************************************************************************/
@Test
@ -136,6 +144,7 @@ class QInstanceValidatorTest
/*******************************************************************************
** Test that if a table has a null backend, that it fails.
**
*******************************************************************************/
@Test
@ -157,6 +166,7 @@ class QInstanceValidatorTest
/*******************************************************************************
** Test that if a table specifies a backend that doesn't exist, that it fails.
**
*******************************************************************************/
@Test
@ -178,6 +188,8 @@ class QInstanceValidatorTest
/*******************************************************************************
** utility method for asserting that a specific reason string is found within
** the list of reasons in the QInstanceValidationException.
**
*******************************************************************************/
private void assertReason(String reason, QInstanceValidationException e)
@ -185,4 +197,4 @@ class QInstanceValidatorTest
assertNotNull(e.getReasons());
assertTrue(e.getReasons().stream().anyMatch(s -> s.contains(reason)));
}
}
}

View File

@ -10,12 +10,14 @@ import static org.junit.jupiter.api.Assertions.*;
/*******************************************************************************
** Unit test for QModuleDispatcher
**
*******************************************************************************/
class QModuleDispatcherTest
{
/*******************************************************************************
** Test success case - a valid backend.
**
*******************************************************************************/
@Test
@ -28,6 +30,7 @@ class QModuleDispatcherTest
/*******************************************************************************
** Test failure case, a backend name that doesn't exist
**
*******************************************************************************/
@Test
@ -41,4 +44,4 @@ class QModuleDispatcherTest
});
}
}
}

View File

@ -16,6 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/*******************************************************************************
** Unit test for CollectionUtils
**
*******************************************************************************/
class CollectionUtilsTest
@ -388,4 +389,4 @@ class CollectionUtilsTest
assertEquals("?", CollectionUtils.getQuestionMarks(List.of(1)));
assertEquals("?,?,?", CollectionUtils.getQuestionMarks(List.of(1, 2, 3)));
}
}
}

View File

@ -8,6 +8,7 @@ import static org.junit.jupiter.api.Assertions.*;
/*******************************************************************************
** Unit test for ExceptionUtils
**
*******************************************************************************/
class ExceptionUtilsTest
@ -26,4 +27,4 @@ class ExceptionUtilsTest
assertSame(target, ExceptionUtils.findClassInRootChain(new QException("decoy", target), QUserFacingException.class));
assertNull(ExceptionUtils.findClassInRootChain(new QException("decoy", target), IllegalArgumentException.class));
}
}
}

View File

@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.fail;
/*******************************************************************************
** Unit test for JsonUtils.
**
*******************************************************************************/
class JsonUtilsTest
@ -269,4 +270,4 @@ class JsonUtilsTest
assertEquals("age", qQueryFilter.getOrderBys().get(0).getFieldName());
assertTrue(qQueryFilter.getOrderBys().get(0).getIsAscending());
}
}
}

View File

@ -14,6 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/*******************************************************************************
** Unit test for ListingHash
**
*******************************************************************************/
class ListingHashTest
@ -329,4 +330,4 @@ class ListingHashTest
assertTrue(values.contains(List.of("Apple", "Acorn")));
assertTrue(values.contains(List.of("Ball")));
}
}
}

View File

@ -10,6 +10,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
/*******************************************************************************
** Unit test for StringUtils
**
*******************************************************************************/
class StringUtilsTest
@ -224,4 +225,4 @@ class StringUtilsTest
assertEquals("", StringUtils.plural(1, "", "es"));
assertEquals("es", StringUtils.plural(2, "", "es"));
}
}
}

View File

@ -9,11 +9,13 @@ import com.kingsrook.qqq.backend.core.model.metadata.QTableMetaData;
/*******************************************************************************
** Utility class for backend-core test classes
**
*******************************************************************************/
public class TestUtils
{
/*******************************************************************************
** Define the instance used in standard tests.
**
*******************************************************************************/
public static QInstance defineInstance()
@ -27,7 +29,7 @@ public class TestUtils
/*******************************************************************************
**
** Define the backend used in standard tests - using 'mock' type.
*******************************************************************************/
public static QBackendMetaData defineBackend()
{
@ -39,7 +41,7 @@ public class TestUtils
/*******************************************************************************
**
** Define the 'person' table used in standard tests.
*******************************************************************************/
public static QTableMetaData defineTablePerson()
{