| /** |
| * |
| * 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); |
| } |
| } |
| } |