mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
Merge branch 'feature/sprint-21' into dev
This commit is contained in:
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2023. 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.actions.queues;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||||
|
import com.amazonaws.auth.BasicAWSCredentials;
|
||||||
|
import com.amazonaws.services.sqs.AmazonSQS;
|
||||||
|
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
|
||||||
|
import com.amazonaws.services.sqs.model.GetQueueAttributesResult;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueProviderMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.queues.SQSQueueProviderMetaData;
|
||||||
|
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class GetQueueSize
|
||||||
|
{
|
||||||
|
private static final QLogger LOG = QLogger.getLogger(GetQueueSize.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public Integer getQueueSize(QQueueProviderMetaData queueProviderMetaData, QQueueMetaData queueMetaData) throws QException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
// todo - handle other queue provider types, somewhere, somehow //
|
||||||
|
//////////////////////////////////////////////////////////////////
|
||||||
|
SQSQueueProviderMetaData queueProvider = (SQSQueueProviderMetaData) queueProviderMetaData;
|
||||||
|
|
||||||
|
BasicAWSCredentials credentials = new BasicAWSCredentials(queueProvider.getAccessKey(), queueProvider.getSecretKey());
|
||||||
|
final AmazonSQS sqs = AmazonSQSClientBuilder.standard()
|
||||||
|
.withRegion(queueProvider.getRegion())
|
||||||
|
.withCredentials(new AWSStaticCredentialsProvider(credentials))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String queueUrl = queueProvider.getBaseURL();
|
||||||
|
if(!queueUrl.endsWith("/"))
|
||||||
|
{
|
||||||
|
queueUrl += "/";
|
||||||
|
}
|
||||||
|
queueUrl += queueMetaData.getQueueName();
|
||||||
|
|
||||||
|
GetQueueAttributesResult queueAttributes = sqs.getQueueAttributes(queueUrl, List.of("ApproximateNumberOfMessages"));
|
||||||
|
String approximateNumberOfMessages = queueAttributes.getAttributes().get("ApproximateNumberOfMessages");
|
||||||
|
return (Integer.parseInt(approximateNumberOfMessages));
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.warn("Error getting queue size", e, logPair("queueName", queueMetaData == null ? "null" : queueMetaData.getName()));
|
||||||
|
throw (new QException("Error getting queue size", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,6 +22,7 @@
|
|||||||
package com.kingsrook.qqq.backend.core.model.metadata.dashboard.nocode;
|
package com.kingsrook.qqq.backend.core.model.metadata.dashboard.nocode;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
||||||
@ -35,6 +36,8 @@ public abstract class AbstractWidgetValueSource
|
|||||||
protected String name;
|
protected String name;
|
||||||
protected String type;
|
protected String type;
|
||||||
|
|
||||||
|
protected Map<String, Serializable> inputValues;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -116,4 +119,35 @@ public abstract class AbstractWidgetValueSource
|
|||||||
////////////////////////
|
////////////////////////
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for inputValues
|
||||||
|
*******************************************************************************/
|
||||||
|
public Map<String, Serializable> getInputValues()
|
||||||
|
{
|
||||||
|
return (this.inputValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for inputValues
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setInputValues(Map<String, Serializable> inputValues)
|
||||||
|
{
|
||||||
|
this.inputValues = inputValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for inputValues
|
||||||
|
*******************************************************************************/
|
||||||
|
public AbstractWidgetValueSource withInputValues(Map<String, Serializable> inputValues)
|
||||||
|
{
|
||||||
|
this.inputValues = inputValues;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2023. 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.model.metadata.dashboard.nocode;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.queues.GetQueueSize;
|
||||||
|
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueMetaData;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.queues.QQueueProviderMetaData;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class QueueSizeWidgetValue extends AbstractWidgetValueSource
|
||||||
|
{
|
||||||
|
private static final QLogger LOG = QLogger.getLogger(QueueSizeWidgetValue.class);
|
||||||
|
|
||||||
|
private String queueName;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public Object evaluate(Map<String, Object> context, RenderWidgetInput input) throws QException
|
||||||
|
{
|
||||||
|
QQueueMetaData queue = QContext.getQInstance().getQueue(queueName);
|
||||||
|
QQueueProviderMetaData queueProvider = QContext.getQInstance().getQueueProvider(queue.getProviderName());
|
||||||
|
return (new GetQueueSize().getQueueSize(queueProvider, queue));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public QueueSizeWidgetValue withName(String name)
|
||||||
|
{
|
||||||
|
setName(name);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for queueName
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getQueueName()
|
||||||
|
{
|
||||||
|
return (this.queueName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for queueName
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setQueueName(String queueName)
|
||||||
|
{
|
||||||
|
this.queueName = queueName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for queueName
|
||||||
|
*******************************************************************************/
|
||||||
|
public QueueSizeWidgetValue withQueueName(String queueName)
|
||||||
|
{
|
||||||
|
this.queueName = queueName;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* QQQ - Low-code Application Framework for Engineers.
|
||||||
|
* Copyright (C) 2021-2023. 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.model.metadata.dashboard.nocode;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import com.kingsrook.qqq.backend.core.actions.customizers.QCodeLoader;
|
||||||
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.actions.widgets.RenderWidgetInput;
|
||||||
|
import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeReference;
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public class WidgetAdHocValue extends AbstractWidgetValueSource
|
||||||
|
{
|
||||||
|
private QCodeReference codeReference;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Constructor
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
public WidgetAdHocValue()
|
||||||
|
{
|
||||||
|
setType(getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public Object evaluate(Map<String, Object> context, RenderWidgetInput input) throws QException
|
||||||
|
{
|
||||||
|
if(inputValues != null)
|
||||||
|
{
|
||||||
|
context.putAll(inputValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
Function<Object, Object> function = QCodeLoader.getFunction(codeReference);
|
||||||
|
Object result = function.apply(context);
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for name
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public WidgetAdHocValue withName(String name)
|
||||||
|
{
|
||||||
|
setName(name);
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for codeReference
|
||||||
|
*******************************************************************************/
|
||||||
|
public QCodeReference getCodeReference()
|
||||||
|
{
|
||||||
|
return (this.codeReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for codeReference
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setCodeReference(QCodeReference codeReference)
|
||||||
|
{
|
||||||
|
this.codeReference = codeReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for codeReference
|
||||||
|
*******************************************************************************/
|
||||||
|
public WidgetAdHocValue withCodeReference(QCodeReference codeReference)
|
||||||
|
{
|
||||||
|
this.codeReference = codeReference;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for inputValues
|
||||||
|
*******************************************************************************/
|
||||||
|
@Override
|
||||||
|
public WidgetAdHocValue withInputValues(Map<String, Serializable> inputValues)
|
||||||
|
{
|
||||||
|
this.inputValues = inputValues;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -74,14 +74,14 @@ public class WidgetCalculation extends AbstractWidgetValueSource
|
|||||||
{
|
{
|
||||||
Instant now = Instant.now();
|
Instant now = Instant.now();
|
||||||
Instant then = ValueUtils.getValueAsInstant(context.get(valueNames.get(0)));
|
Instant then = ValueUtils.getValueAsInstant(context.get(valueNames.get(0)));
|
||||||
return (then.until(now, ChronoUnit.MINUTES));
|
return (then == null ? null : then.until(now, ChronoUnit.MINUTES));
|
||||||
}),
|
}),
|
||||||
|
|
||||||
AGE_SECONDS((List<String> valueNames, Map<String, Object> context) ->
|
AGE_SECONDS((List<String> valueNames, Map<String, Object> context) ->
|
||||||
{
|
{
|
||||||
Instant now = Instant.now();
|
Instant now = Instant.now();
|
||||||
Instant then = ValueUtils.getValueAsInstant(context.get(valueNames.get(0)));
|
Instant then = ValueUtils.getValueAsInstant(context.get(valueNames.get(0)));
|
||||||
return (then.until(now, ChronoUnit.SECONDS));
|
return (then == null ? null : then.until(now, ChronoUnit.SECONDS));
|
||||||
}),
|
}),
|
||||||
|
|
||||||
PERCENT_CHANGE((List<String> valueNames, Map<String, Object> context) ->
|
PERCENT_CHANGE((List<String> valueNames, Map<String, Object> context) ->
|
||||||
@ -92,8 +92,8 @@ public class WidgetCalculation extends AbstractWidgetValueSource
|
|||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
// 100 * ( (current - previous) / previous ) //
|
// 100 * ( (current - previous) / previous ) //
|
||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
BigDecimal difference = current.subtract(previous);
|
BigDecimal difference = current == null ? null : current.subtract(previous);
|
||||||
if(BigDecimal.ZERO.equals(previous))
|
if(BigDecimal.ZERO.equals(previous) || difference == null)
|
||||||
{
|
{
|
||||||
return (null);
|
return (null);
|
||||||
}
|
}
|
||||||
|
@ -313,6 +313,42 @@ public class StringUtils
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Given a "formatString" containing any number of {singular,plural} style "tokens",
|
||||||
|
** replace the "tokens" with the "singular" options if the 'size' parameter is 1
|
||||||
|
** or the "plural" options if not-1 (e.g., 0 or 2+)
|
||||||
|
**
|
||||||
|
** e.g.: StringUtils.pluralFormat(n, "Apple{,s} {was,were} eaten")) // seems easier.
|
||||||
|
** e.g.: StringUtils.pluralFormat(n, "Apple{ was,s were} eaten")) // also works...
|
||||||
|
*******************************************************************************/
|
||||||
|
public static String pluralFormat(Integer size, String formatString)
|
||||||
|
{
|
||||||
|
int lastIndex = 0;
|
||||||
|
StringBuilder output = new StringBuilder();
|
||||||
|
|
||||||
|
Pattern pattern = Pattern.compile("\\{.*?,.*?}");
|
||||||
|
Matcher matcher = pattern.matcher(formatString);
|
||||||
|
while(matcher.find())
|
||||||
|
{
|
||||||
|
String group = matcher.group();
|
||||||
|
String groupBody = group.substring(1, group.length() - 1);
|
||||||
|
String[] groupParts = groupBody.split(",", 2);
|
||||||
|
String replacement = (size == 1) ? groupParts[0] : groupParts[1];
|
||||||
|
output.append(formatString, lastIndex, matcher.start()).append(replacement);
|
||||||
|
|
||||||
|
lastIndex = matcher.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lastIndex < formatString.length())
|
||||||
|
{
|
||||||
|
output.append(formatString, lastIndex, formatString.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (output.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Switch between strings based on if the size of the parameter collection. If
|
** 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"
|
** it is 1 (the singular) or not-1 (0 or 2+, the plural). Get back "" or "s"
|
||||||
|
@ -285,4 +285,23 @@ class StringUtilsTest extends BaseTest
|
|||||||
assertEquals("Abc", StringUtils.ucFirst("abc"));
|
assertEquals("Abc", StringUtils.ucFirst("abc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
void testPluralFormat()
|
||||||
|
{
|
||||||
|
assertEquals("Apple", StringUtils.pluralFormat(1, "Apple{,s}"));
|
||||||
|
assertEquals("Apples", StringUtils.pluralFormat(0, "Apple{,s}"));
|
||||||
|
assertEquals("Apples", StringUtils.pluralFormat(2, "Apple{,s}"));
|
||||||
|
|
||||||
|
assertEquals("Apple and Orange", StringUtils.pluralFormat(1, "Apple{,s} and Orange{,s}"));
|
||||||
|
assertEquals("Apples and Oranges", StringUtils.pluralFormat(2, "Apple{,s} and Orange{,s}"));
|
||||||
|
|
||||||
|
assertEquals("Apple was eaten", StringUtils.pluralFormat(1, "Apple{,s} {was,were} eaten"));
|
||||||
|
assertEquals("Apples were eaten", StringUtils.pluralFormat(2, "Apple{,s} {was,were} eaten"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ import java.time.LocalTime;
|
|||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@ -49,6 +50,7 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||||
import org.apache.commons.lang.NotImplementedException;
|
import org.apache.commons.lang.NotImplementedException;
|
||||||
@ -59,6 +61,8 @@ import org.apache.commons.lang.NotImplementedException;
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public class QueryManager
|
public class QueryManager
|
||||||
{
|
{
|
||||||
|
private static final QLogger LOG = QLogger.getLogger(QueryManager.class);
|
||||||
|
|
||||||
public static final int DEFAULT_PAGE_SIZE = 2000;
|
public static final int DEFAULT_PAGE_SIZE = 2000;
|
||||||
public static int PAGE_SIZE = DEFAULT_PAGE_SIZE;
|
public static int PAGE_SIZE = DEFAULT_PAGE_SIZE;
|
||||||
|
|
||||||
@ -1409,13 +1413,44 @@ public class QueryManager
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static Instant getInstant(ResultSet resultSet, int column) throws SQLException
|
public static Instant getInstant(ResultSet resultSet, int column) throws SQLException
|
||||||
{
|
{
|
||||||
Timestamp value = resultSet.getTimestamp(column);
|
try
|
||||||
if(resultSet.wasNull())
|
|
||||||
{
|
{
|
||||||
return (null);
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
}
|
// this will be a zone-less date-time string, in the database server's configured timezone //
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
String string = resultSet.getString(column);
|
||||||
|
if(resultSet.wasNull())
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
return (value.toInstant());
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// make an Instant (which means UTC) from that zone-less date-time string. //
|
||||||
|
// if the database server was giving back non-utc times, we'd need a different ZoneId here? //
|
||||||
|
// e.g., as configured via ... a system property or database metadata setting //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.parse(string.replace(' ', 'T'));
|
||||||
|
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("UTC"));
|
||||||
|
Instant instant = zonedDateTime.toInstant();
|
||||||
|
return (instant);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
LOG.error("Error getting an instant value from a database result - proceeding with potentially wrong-timezone implementation...", e);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// if for some reason the parsing and stuff above fails, well, this will give us back "some" date, maybe //
|
||||||
|
// this was our old logic, which probably had timezones wrong if server wasn't in UTC //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Timestamp value = resultSet.getTimestamp(column);
|
||||||
|
if(resultSet.wasNull())
|
||||||
|
{
|
||||||
|
return (null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Instant instant = value.toInstant();
|
||||||
|
return (instant);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user