Skip to content

Commit

Permalink
[JBPM-10174] Supporting date conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
fjtirado committed Jun 2, 2023
1 parent 0d2883d commit 268bc2a
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,24 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Optional;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.security.ExplicitTypePermission;
import org.drools.reflective.classloader.ProjectClassLoader;
import org.jbpm.process.core.datatype.DataType;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;

import static org.kie.soup.xstream.XStreamUtils.createTrustingXStream;

Expand All @@ -37,6 +45,7 @@
*/
public class ObjectDataType implements DataType {

private static final Logger logger = LoggerFactory.getLogger(ObjectDataType.class);
private static final long serialVersionUID = 510l;

private String className;
Expand Down Expand Up @@ -79,55 +88,85 @@ public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(className);
}

public boolean verifyDataType(final Object value) {
if (value == null || className == null) {
return true;
}
private static final Collection<String> prefixes = Arrays.asList("java.lang", "java.util", "java.time");

private Optional<Class<?>> getClass(Object value) {
try {
Class<?> clazz = Class.forName(className, true, value.getClass().getClassLoader());
if (clazz.isInstance(value) || isValidDate(value)) {
return true;
}
return Optional.of(Class.forName(className, true, value.getClass().getClassLoader()));
} catch (ClassNotFoundException e) {
// check class again
logger.info("Error {} loading class {}", e, className);
}
// try to expand fundamental classes if it's not a FQCN
if(!className.contains(".")) {
try {
className = "java.lang."+className;
Class<?> clazz = Class.forName(className, true, value.getClass().getClassLoader());
if (clazz.isInstance(value)) {
return true;
if (!className.contains(".")) {
for (String prefix : prefixes) {
String altName = prefix + "." + className;
try {
return Optional.of(Class.forName(altName, true, classLoader));
} catch (ClassNotFoundException e) {
logger.debug("Error {} loading class {}", e, altName);
}
} catch (ClassNotFoundException e) {
return false;
}
}
return false;
return Optional.empty();
}

public boolean verifyDataType(final Object value) {
if (value == null || className == null) {
return true;
}
return getClass(value).map(c -> c.isInstance(value)).orElse(false);
}

private boolean isValidDate(Object value) {
boolean parseable = false;
try{
parseable = LocalDate.parse((String)value)!=null;
} catch(Exception e) {
// ignore parse exception
private Optional<Object> getObjectFromClass(final Object value) {
if (value == null) {
return null;
}
try{
parseable = LocalDateTime.parse((String)value)!=null;
} catch(Exception e) {
// ignore parse exception
Optional<Class<?>> clazz = getClass(value);
if (clazz.isPresent()) {
Class<?> objectClass = clazz.get();
if (objectClass.isInstance(value)) {
return Optional.of(value);
}
if (Date.class.isAssignableFrom(objectClass)) {
return Optional.of(parseDate(value.toString()));
} else if (LocalDate.class.isAssignableFrom(objectClass)) {
return Optional.of(LocalDate.parse((value.toString())));
} else if (LocalDateTime.class.isAssignableFrom(objectClass)) {
return Optional.of(LocalDateTime.parse((value.toString())));
} else if (ZonedDateTime.class.isAssignableFrom(objectClass)) {
return Optional.of(ZonedDateTime.parse((value.toString())));
}
}
try{
parseable = ZonedDateTime.parse((String)value)!=null;
} catch(Exception e) {
// ignore parse exception
return Optional.empty();
}

private static Collection<DateFormat> dateFormats = Arrays.asList(DateFormat.getDateInstance(),
DateFormat.getTimeInstance(), DateFormat.getDateTimeInstance(), new SimpleDateFormat("yyyy/MM/dd"),
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"), new SimpleDateFormat("HH:mm:ss"));

private Date parseDate(String toBeParsed) {
StringBuilder sb = new StringBuilder();
for (DateFormat dateFormat : dateFormats) {
try {
return dateFormat.parse(toBeParsed);
} catch (ParseException ex) {
sb.append(ex.getMessage()).append(System.lineSeparator());
}
}
return parseable;
throw new IllegalArgumentException(sb.toString());
}

@Override
public Object readValue(String value) {
return getXStream().fromXML(value);
return getObjectFromClass(value).orElseGet(() -> getXStream().fromXML(value));
}

@Override
public Object valueOf(String value) {
try {
return getObjectFromClass(value).orElse(value);
} catch (Exception e) {
return value;
}
}

public String writeValue(Object value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public ProcessInstance createProcessInstance(Process process, CorrelationKey cor
throw new IllegalArgumentException( "This process does not support parameters!" );
}
}
variableScopeInstance.setDefaultValues(variableScope, variableScopeInstance);
variableScopeInstance.setDefaultValues(variableScope, variableScopeInstance);
variableScopeInstance.enforceRequiredVariables();

return processInstance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,15 @@ private boolean hasData(Object data) {
return data != null && (!(data instanceof CharSequence) || !data.toString().trim().isEmpty());
}

public void setDefaultValues(VariableScope variableScope, VariableScopeInstance variableScopeInstance) {
if (variableScope != null) {
for (Variable variable : variableScope.getVariables()) {
String name = variable.getName();
Object defaultValue = variable.getMetaData("defaultValue");
if (variableScopeInstance.getVariable(name) == null && defaultValue != null) {
variableScopeInstance.setVariable(name, variable.getType().readValue(defaultValue.toString()));
}
}
}
}
public void setDefaultValues(VariableScope variableScope, VariableScopeInstance variableScopeInstance) {
if (variableScope != null) {
for (Variable variable : variableScope.getVariables()) {
String name = variable.getName();
Object defaultValue = variable.getMetaData("defaultValue");
if (variableScopeInstance.getVariable(name) == null && defaultValue != null) {
variableScopeInstance.setVariable(name, variable.getType().readValue(defaultValue.toString()));
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2023 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.process.core.datatype.impl;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Date;

import org.jbpm.process.core.datatype.impl.type.ObjectDataType;
import org.junit.Test;

public class ObjectDataTypeTest {

@Test
public void testReadValueDate() {
ObjectDataType dateType = new ObjectDataType(Date.class.getCanonicalName());
assertThat(dateType.readValue("02/02/2012")).isInstanceOf(Date.class);
assertThat(dateType.readValue("02/02/2012 12:12:12")).isInstanceOf(Date.class);
assertThat(dateType.readValue("12:12:12")).isInstanceOf(Date.class);
}
}

0 comments on commit 268bc2a

Please sign in to comment.