blob: 41e3d38ca3ab541b9d89847088ab081954c73970 [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*
*/
package org.eclipse.osbp.xtext.datainterchange.common;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Subquery;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.osbp.core.api.persistence.IPersistenceService;
import org.eclipse.osbp.datainterchange.api.IDataInterchangeExecutionEvent;
import org.eclipse.osbp.datainterchange.api.IDataInterchangeExecutionEventListener;
import org.eclipse.osbp.dsl.common.datatypes.IDto;
import org.eclipse.osbp.runtime.common.event.IEventDispatcher;
import org.eclipse.osbp.ui.api.customfields.IBlobService;
import org.eclipse.osbp.xtext.datainterchange.common.CriteriaGenerator.WhereClausel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.ProgressBar;
import com.vaadin.ui.UI;
public abstract class WorkerThreadRunnable implements Runnable, IDataInterchangeExecutionEventListener {
static final Logger log = LoggerFactory.getLogger("dataInterchange");
private String name = null;
private String status = null;
private IEventDispatcher eventDispatcher;
private ProgressBar progressBar;
private HorizontalLayout progressBarArea;
private IPersistenceService persistenceService;
private long counter = 0;
private long length = 0;
private long avgElementSize = 0;
private float previousValue = 0.0f;
private UI ui = null;
private URL fileURL;
private SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddhhmmssa", Locale.US);
public enum Direction {
IMPORT, EXPORT
}
private Direction direction = Direction.IMPORT;
private IBlobService blobService;
private boolean deleteFileAfterImport = false;
private boolean failedExecution = false;
private boolean executionDone = false;
private boolean actionFilterExecutionNeeded = false;
private float progress;
private final String ERROR_MESSAGE = "The directory you've chosen does not exist or is not accessible. Please adapt the url.";
private HashMap<String, Parameter> filterParameters;
public WorkerThreadRunnable() {
progressBarArea = new HorizontalLayout();
progressBar = new ProgressBar();
progressBarArea.addComponent(progressBar);
}
public void setLength(long length) {
this.length = length;
}
public void setAvgElementSize(long avgElementSize) {
this.avgElementSize = avgElementSize;
}
public void setProgressBarStyleName(String styleName) {
progressBar.addStyleName(styleName);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
progressBar.setDescription(name);
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public IEventDispatcher getEventDispatcher() {
return eventDispatcher;
}
public void setEventDispatcher(IEventDispatcher eventDispatcher) {
this.eventDispatcher = eventDispatcher;
}
public void setBlobService(IBlobService blobService) {
this.blobService = blobService;
}
public IBlobService getBlobService() {
return blobService;
}
public IPersistenceService getPersistenceService() {
return persistenceService;
}
public void setPersistenceService(IPersistenceService persistenceService) {
this.persistenceService = persistenceService;
}
public ProgressBar getProgressBar() {
return progressBar;
}
public HorizontalLayout getProgressBarArea() {
return progressBarArea;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public UI getUi() {
return ui;
}
public void setUi(UI ui) {
this.ui = ui;
}
public void setProgressBarEnabled(final boolean enable) {
if (ui != null) {
ui.access(() -> progressBar.setEnabled(enable));
}
}
public void setProgressIndeterminated(final boolean indeterminate) {
if (ui != null) {
ui.access(() -> progressBar.setIndeterminate(indeterminate));
}
}
@Override
public void onEvent(IDataInterchangeExecutionEvent event) {
if (ui != null) {
switch (event.getType()) {
case STARTED:
ui.access(() -> {
progressBar.setValue(0.0f);
progressBar.setEnabled(false);
});
break;
case FINISHED:
ui.access(() -> {
progressBar.setValue(1.0f);
progressBar.setIndeterminate(true);
});
break;
case ELEMENT:
counter++;
if (length != 0) {
progress = ((float) counter * avgElementSize) / length;
if (Math.abs(progress - previousValue) > 0.01) {
ui.access(() -> {
log.debug("progress {}", progress);
progressBar.setValue(progress);
previousValue = progress;
});
}
}
break;
}
}
}
/**
* Sets the {@link #fileURL}.
*
* @param filepath
* the file URl
*/
public void setFileURL(String filepath) {
fileURL = null;
try {
fileURL = new URL(filepath);
} catch (MalformedURLException e1) {
if (e1.getMessage().startsWith("unknown protocol") || e1.getMessage().startsWith("no protocol")) {
try {
fileURL = Paths.get(filepath).toUri().toURL();
} catch (MalformedURLException e2) {
StringWriter sw = new StringWriter();
e2.printStackTrace(new PrintWriter(sw));
log.error("{}", sw);
}
}
}
// fileURL = produceAppropiateInterchangeURL(filepath);
}
/**
* Gives the {@link #fileURL}.
*
* @return {@link URL} the file url
*/
public URL getFileURL() {
return this.fileURL;
}
/**
* Checks whether the import file has to be deleted at the end of the
* process.
*
* @return true if yes, false if not
*/
public boolean isDeleteFileAfterImport() {
return deleteFileAfterImport;
}
/**
* Sets whether the import file has to be deleted at the end of the process.
*
* @param deleteFileAfterImport
*/
public void setDeleteFileAfterImport(boolean deleteFileAfterImport) {
this.deleteFileAfterImport = deleteFileAfterImport;
}
/**
* Make sure that the given file is deleted.
*
* @param file
* the file to rename
* @param logidinfo
* log information from the caller.
*/
public void deleteFile(final Path file, String logidinfo) {
try {
if (Files.deleteIfExists(file)) {
log.info("{} [{}] successfuly removed.", logidinfo, file);
} else {
log.info("{} [{}] doesn't exist and could not be removed.", logidinfo, file);
}
} catch (IOException e) {
log.error("{} [{}] could not be deleted.\n{}", logidinfo, file, e.getMessage());
}
}
/**
* Renames the given file with the given new name. If a file with the given
* new name already exists then a number offset will be added to it.
*
* @param file
* the file to rename
* @param newname
* the new file name
*/
public void renameFile(final Path file, String newname) {
try {
if (Files.exists(file)) {
String filename = file.getFileName().toString();
if (newname == null || newname.isEmpty()) {
log.info("file [{}] has not been renamed!", filename);
} else {
int renameTry = 0;
boolean done = false;
String tempname = newname;
String extension = newname.substring(newname.length() - 4);
do {
try {
Files.move(file, file.resolveSibling(tempname));
done = true;
} catch (FileAlreadyExistsException ae) {
renameTry++;
tempname = newname.replace(extension, renameTry + extension);
}
} while (!done);
log.info("file [{}] renamed to {}.", filename, tempname);
}
} else {
log.info("file [{}] doesn't exist and could not be renamed.", file);
}
} catch (IOException e) {
log.error("file [{}] could not be renamed.\n{}", file, e.getMessage());
}
}
/**
* Checks whether the import or export execution is done.
*
* @return true if yes, false if not
*/
public boolean isExecutionDone() {
return executionDone;
}
/**
* Sets whether the import or export execution is done.
*
* @param executionDone
* the execution state
*/
public void setExecutionDone(boolean executionDone) {
this.executionDone = executionDone;
}
/**
* Checks whether the import or export execution has failed.
*
* @return true if yes, false if not
*/
public boolean hasExecutionFailed() {
return failedExecution;
}
/**
* Sets whether the import or export execution has failed.
*
* @param failedExecution
* the new state
*/
public void setExecutionFailed(boolean failedExecution) {
this.failedExecution = failedExecution;
}
/**
* Gives the {@link #formatter}.
*
* @return {@link SimpleDateFormat}
*/
public SimpleDateFormat getFormatter() {
return formatter;
}
/**
* Generates the right directory url depending on whether the given file
* path is relative or absolute.
*
* @return the URL
*/
public URL produceAppropiateInterchangeURL(String filepath) {
URL url = null;
String filename = null;
String directory = null;
if (filepath != null && !filepath.isEmpty()) {
int index = filepath.lastIndexOf("/");
if (index != -1) {
directory = filepath.substring(0, index + 1);
filename = filepath.substring(index + 1, filepath.length());
} else {
index = filepath.lastIndexOf("\\");
if (index != -1) {
directory = filepath.substring(0, index + 1);
filename = filepath.substring(index + 1, filepath.length());
}
}
// TODO for relative path check if directory is valid
// check most needed for configuration file entries
if (directory != null && !directory.isEmpty() && filename != null && !filename.isEmpty()) {
try {
url = new URL(filepath);
if (url.getProtocol().equals("file")) {
// do nothing for now
}
} catch (InvalidPathException | MalformedURLException e1) {
if (e1.getMessage().startsWith("unknown protocol") || e1.getMessage().startsWith("no protocol")) {
try {
if (!Paths.get(filepath).isAbsolute()) { // check
// for
// relative
// path
IPath folderlocation = null;
// check if WITHIN all projects a directory
// exists corresponding to the relative path
for (IProject prj : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
IPath templocation = prj.getFolder(directory).getLocation();
Path folder = Paths.get(templocation.toString());
if (folder != null && folder.toFile() != null) {
// find the first folder
folderlocation = templocation;
break;
}
// else 1. in the base projects for ../..
// else 2. outside the base project
}
File file = Paths.get(folderlocation.append(filename).toOSString()).toFile();
if (file != null && file.exists() && file.isDirectory()) {
url = Paths.get(folderlocation.append(filename).toString()).toUri().toURL();
} else {
// TODO to be cleared with Joerg, if fale
// safe is needed
// if the folder doesn't exist then use the
// base directory as main location for all
// interchanges
// url =
// Paths.get(ResourcesPlugin.getWorkspace().getRoot().getProjectRelativePath().append(filename).toString()).toUri().toURL();
throw new InvalidPathException(ERROR_MESSAGE, filepath);
}
} else { // for absolute paths that were malformed
// or else
url = Paths.get(filepath).toUri().toURL();
}
} catch (InvalidPathException | MalformedURLException e2) {
StringWriter sw = new StringWriter();
e2.printStackTrace(new PrintWriter(sw));
log.error("{}", sw);
}
}
}
}
}
// if the path is absolute or from another protocol like http, ftp ...
// just return
return url;
}
/**
* Returns the path of the given file name or directory name.
*/
public IPath findProjectFileOrFolderLocation(String projectname, String fname, boolean isFile) {
if (projectname != null && !projectname.isEmpty() && fname != null && !fname.isEmpty()) {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectname);
if (isFile) {
return project.getFile(fname).getLocation();
}
return project.getFolder(fname).getLocation();
}
return null;
}
public void setFilter(HashMap<String, Parameter> param) {
this.filterParameters = param;
}
public HashMap<String, Parameter> getFilter() {
return this.filterParameters;
}
public boolean hasFilter() {
return (this.filterParameters != null && !this.filterParameters.isEmpty());
}
public boolean isActionFilterExecutionNeeded() {
return actionFilterExecutionNeeded;
}
public void setActionFilterExecutionNeeded(boolean actionFilterExecutionNeeded) {
this.actionFilterExecutionNeeded = actionFilterExecutionNeeded;
}
/**
* Check if the given value is nor null or empty and gives it back or give the default value.
* In case, even the default value is not defined an empty string will be given.
* @param value the criteria value
* @param defaultValue the default value
* @return the appropriate criteria value or an empty string.
*/
public String getCriteriaValue(String value, String defaultValue){
if(value != null && !value.isEmpty()){
return value;
}
if(defaultValue != null && !defaultValue.isEmpty()){
return defaultValue;
}
return "";
}
/**
*
* @param entityname
* @param filename
* @param isroot
* @return
*/
public Object[] createExportFileComponents(String entityname, String filename, boolean isroot){
int openTry = 0;
Path exportPath = null;
OutputStream fileStr = null;
OutputStream outStr = null;
URI uri = null;
try {
uri = getFileURL().toURI();
String uriValue = uri.toString();
if(isroot){
uri = new URI(uriValue+"tmp");
}else{
String location = uriValue.substring(0, uriValue.lastIndexOf("/")+1);
uri = new URI(location+filename+"tmp");
}
} catch (URISyntaxException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
}
do {
try {
exportPath = Paths.get(uri);
// find a unique name - similar to given
fileStr = Files.newOutputStream(exportPath, StandardOpenOption.CREATE_NEW);
} catch (FileAlreadyExistsException ae) {
openTry ++;
try {
int pos = uri.toString().lastIndexOf('.');
if(pos == -1) {
uri = new URI(uri.toString()+openTry);
} else {
uri = new URI(uri.toString().substring(0,pos)+openTry+"."+uri.toString().substring(pos+1));
}
} catch (URISyntaxException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
break;
}
} catch (IOException e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log.error("{}", sw.toString());
break;
}
}while(fileStr == null);
if(exportPath != null && exportPath.toFile() != null && exportPath.toFile().exists()){
log.debug("Temporary export file [{}] for entity {} created", exportPath, entityname);
}else{
log.debug("No temporary export file [{}] for entity {} created", exportPath, entityname);
}
outStr = new BufferedOutputStream(fileStr);
return new Object[]{exportPath, fileStr, outStr};
}
public Subquery generateSubQuery(CriteriaBuilder criteriaBuilder, Class rootclass, WhereClausel filter){
return CriteriaGenerator.generateSubQuery(criteriaBuilder, rootclass, filter);
}
public CriteriaQuery generateCriteriaQuery(CriteriaBuilder criteriaBuilder, Class rootclass, WhereClausel filter){ //List<String> values){
return CriteriaGenerator.generateCriteriaQuery(criteriaBuilder, rootclass, filter); //List<String> values){;
}
public CriteriaQuery generateCriteriaQueryIn(CriteriaBuilder criteriaBuilder, Class rootclass, String column, List<String> values){
return CriteriaGenerator.generateCriteriaQueryIn(criteriaBuilder, rootclass, column, values);
}
public Expression generateUpdateQueryExpression(CriteriaBuilder builder, String from, String set, String where){
return CriteriaGenerator.generateUpdateQueryExpression(builder, from, set, where);
}
public Expression generateDeleteQueryExpression(CriteriaBuilder builder, String from, String where, String groupby, String having, String orderby){
return CriteriaGenerator.generateDeleteQueryExpression(builder, from, where, groupby, having, orderby);
}
public Expression generateQueryExpression(CriteriaBuilder builder, String query){
return CriteriaGenerator.generateQueryExpression(builder, query);
}
/**
* Helper class to withhold filter parameter.
*/
public static class Parameter {
private String name;
private Object rawValue;
private String stringValue;
public Parameter(String name, Object value) {
super();
this.name = name;
this.rawValue = value;
setStringValue();
}
public String getName() {
return name;
}
public String getValue() {
return stringValue;
}
/**
* Generates the string value of the given raw value object.
*/
private void setStringValue(){
// TODO check the dto validity here and futher datatypes, Build or insert a value converter
if(rawValue != null){
if(rawValue instanceof java.util.Date){
java.util.Date temp = (java.util.Date) rawValue;
java.sql.Date result = new java.sql.Date(temp.getYear(), temp.getMonth(), temp.getDay());
result.setTime(temp.getTime());
rawValue = result;
stringValue = rawValue.toString();
}
else if(rawValue instanceof IDto){
stringValue = rawValue.toString();
}
else {
log.debug("VALUE TYPE is ", rawValue.toString());
stringValue = "";
}
}
else{
stringValue = "";
}
}
@Override
public String toString() {
return name+" ["+stringValue+"]";
}
/**
* Returns the raw saved object
* @return Object the saved object value
*/
public Object getRawValue(){
return rawValue;
}
/**
* Return the appropriate expression for the criteria builder select statement
* @param builder the criteria builder
* @return the created expression
*/
public Expression getExpression(CriteriaBuilder builder){
if(builder != null && rawValue != null){
if(rawValue instanceof java.sql.Date){
return builder.literal(rawValue);
}
}
// TODO Franck extension for all expression types, view link bellow
// https://www.objectdb.com/java/jpa/query/jpql/expression
return builder.nullLiteral(null);
}
}
}