/**
*
*/
package org.goko.tools.macro.service;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
import org.goko.core.common.exception.GkException;
import org.goko.core.common.exception.GkTechnicalException;
import org.goko.core.common.io.xml.IXmlPersistenceProvider;
import org.goko.core.common.io.xml.IXmlPersistenceService;
import org.goko.core.common.service.IGokoService;
import org.goko.core.common.utils.CacheByKey;
import org.goko.core.log.GkLog;
import org.goko.core.workspace.service.IExporter;
import org.goko.core.workspace.service.ILoader;
import org.goko.core.workspace.service.IMapperProvider;
import org.goko.core.workspace.service.IMapperService;
import org.goko.tools.macro.bean.GCodeMacro;
import org.goko.tools.macro.io.bean.XmlGCodeMacro;
import org.goko.tools.macro.io.bean.XmlGCodeMacroReference;
import org.goko.tools.macro.io.exporter.XmlGCodeMacroExporter;
import org.goko.tools.macro.io.exporter.XmlGCodeMacroReferenceExporter;
import org.goko.tools.macro.io.loader.XmlGCodeMacroLoader;
import org.goko.tools.macro.io.loader.XmlGCodeMacroReferenceLoader;
/**
* Services to initialize the Macro service
*
* @author Psyko
* @date 16 oct. 2016
*/
public class DefaultGCodeMacroPersistenceService implements IGokoService, IGCodeMacroServiceListener, IMapperProvider, IXmlPersistenceProvider {
private static final GkLog LOG = GkLog.getLogger(DefaultGCodeMacroPersistenceService.class);
private static final String SERVICE_ID = "org.goko.tools.macro.service.DefaultGCodeMacroPersistenceService";
/** The XML persistence service to read macros files */
private IXmlPersistenceService xmlPersistenceService;
/** The macro service to initialize */
private IGCodeMacroService gcodeMacroService;
/** Cache of file for macros id */
private CacheByKey<Integer, File> cacheFileByMacro;
/** The Mapper service */
private IMapperService mapperService;
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#getServiceId()
*/
@Override
public String getServiceId() throws GkException {
return SERVICE_ID;
}
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#start()
*/
@Override
public void start() throws GkException {
this.cacheFileByMacro = new CacheByKey<Integer, File>();
this.xmlPersistenceService.addXmlPersistenceProvider(this);
this.mapperService.addMapperProvider(this);
initialize();
gcodeMacroService.addListener(this);
}
private void initialize() throws GkException{
try {
Location workspace = Platform.getInstanceLocation();
URL data = workspace.getURL();
Path uri = Paths.get(data.toURI());
Path macroFolderPath = uri.resolve("macros");
File macroFolder = macroFolderPath.toFile();
if(!macroFolder.exists()){
macroFolder.mkdirs();
}
LOG.info("Loading macros from ["+macroFolder.getAbsolutePath()+"]");
File[] lstFiles = macroFolder.listFiles();
if(lstFiles != null && lstFiles.length > 0){
for (File file : lstFiles) {
if(file.isFile()){
loadMacroFromFile(file);
}
}
}
List<GCodeMacro> lstMacros = gcodeMacroService.getGCodeMacro();
LOG.info(CollectionUtils.size(lstMacros)+" macros loaded");
} catch (URISyntaxException e) {
LOG.error(e);
}
}
protected void loadMacroFromFile(File file) throws GkException{
FileInputStream input = null;
try {
input = new FileInputStream(file);
XmlGCodeMacro xmlMacro = xmlPersistenceService.read(XmlGCodeMacro.class, input);
GCodeMacro macro = mapperService.load(xmlMacro, GCodeMacro.class);
gcodeMacroService.addGCodeMacro(macro);
cacheFileByMacro.add(macro.getId(), file);
} catch (FileNotFoundException e) {
throw new GkTechnicalException(e);
}finally{
if(input != null){
IOUtils.closeQuietly(input);
}
}
}
/** (inheritDoc)
* @see org.goko.core.common.service.IGokoService#stop()
*/
@Override
public void stop() throws GkException {
// TODO Auto-generated method stub
}
/**
* @return the gcodeMacroService
*/
public IGCodeMacroService getGCodeMacroService() {
return gcodeMacroService;
}
/**
* @param gcodeMacroService the gcodeMacroService to set
*/
public void setGCodeMacroService(IGCodeMacroService gcodeMacroService) {
this.gcodeMacroService = gcodeMacroService;
}
/**
* @return the xmlPersistenceService
*/
public IXmlPersistenceService getXmlPersistenceService() {
return xmlPersistenceService;
}
/**
* @param xmlPersistenceService the xmlPersistenceService to set
*/
public void setXmlPersistenceService(IXmlPersistenceService xmlPersistenceService) {
this.xmlPersistenceService = xmlPersistenceService;
}
/**
* @return the mapperService
*/
public IMapperService getMapperService() {
return mapperService;
}
/**
* @param mapperService the mapperService to set
*/
public void setMapperService(IMapperService mapperService) {
this.mapperService = mapperService;
}
/** (inheritDoc)
* @see org.goko.tools.macro.service.IGCodeMacroServiceListener#onGCodeMacroCreate(org.goko.tools.macro.bean.GCodeMacro)
*/
@Override
public void onGCodeMacroCreate(GCodeMacro macro) {
try {
String filename = generateFileNameByMacro(macro);
Location workspace = Platform.getInstanceLocation();
URL data = workspace.getURL();
Path uri = Paths.get(data.toURI());
Path macroFolderPath = uri.resolve("macros");
File macroFile = new File(macroFolderPath.toFile(), filename);
macroFile.createNewFile();
OutputStream output = new FileOutputStream(macroFile);
XmlGCodeMacro xmlMacro = mapperService.export(macro, XmlGCodeMacro.class);
xmlPersistenceService.write(xmlMacro, output);
cacheFileByMacro.add(macro.getId(), macroFile);
output.close();
} catch (URISyntaxException | GkException | IOException e) {
LOG.error(e);
}
}
protected void saveMacroToFile(GCodeMacro macro) throws GkException{
OutputStream output = null;
try {
String filename = generateFileNameByMacro(macro);
Location workspace = Platform.getInstanceLocation();
URL data = workspace.getURL();
Path uri = Paths.get(data.toURI());
Path macroFolderPath = uri.resolve("macros");
File macroFile = new File(macroFolderPath.toFile(), filename);
macroFile.createNewFile();
output = new FileOutputStream(macroFile);
XmlGCodeMacro xmlMacro = mapperService.export(macro, XmlGCodeMacro.class);
xmlPersistenceService.write(xmlMacro, output);
output.flush();
output.close();
} catch (URISyntaxException | IOException e) {
LOG.error(e);
}finally{
if(output != null){
IOUtils.closeQuietly(output);
}
}
}
/** (inheritDoc)
* @see org.goko.tools.macro.service.IGCodeMacroServiceListener#onGCodeMacroUpdate(org.goko.tools.macro.bean.GCodeMacro)
*/
@Override
public void onGCodeMacroUpdate(GCodeMacro macro) {
try{
File previousFile = getFileByMacro(macro);
String fileName = generateFileNameByMacro(macro);
if(!StringUtils.equals(previousFile.getName(), fileName)){
previousFile.delete();
}
saveMacroToFile(macro);
}catch(GkException e){
LOG.error(e);
}
}
/** (inheritDoc)
* @see org.goko.tools.macro.service.IGCodeMacroServiceListener#beforeGCodeMacroDelete(org.goko.tools.macro.bean.GCodeMacro)
*/
@Override
public void beforeGCodeMacroDelete(GCodeMacro macro) {
}
/** (inheritDoc)
* @see org.goko.tools.macro.service.IGCodeMacroServiceListener#afterGCodeMacroDelete(org.goko.tools.macro.bean.GCodeMacro)
*/
@Override
public void afterGCodeMacroDelete(GCodeMacro macro) {
try {
File file = getFileByMacro(macro);
if(file.exists()){
file.delete();
}
} catch (GkException e) {
LOG.error(e);
}
}
protected File getFileByMacro(GCodeMacro macro) throws GkException{
return cacheFileByMacro.get(macro.getId());
}
protected String generateFileNameByMacro(GCodeMacro macro)throws GkException{
String filename = StringUtils.deleteWhitespace(macro.getCode());
filename = StringUtils.stripAccents(filename);
return filename+".gkm";
}
/** (inheritDoc)
* @see org.goko.core.common.io.xml.IXmlPersistenceProvider#getSupportedClass()
*/
@Override
public List<Class<?>> getSupportedClass() throws GkException {
List<Class<?>> supportedClass = new ArrayList<Class<?>>();
supportedClass.add(XmlGCodeMacro.class);
supportedClass.add(XmlGCodeMacroReference.class);
return supportedClass;
}
/** (inheritDoc)
* @see org.goko.core.workspace.service.IMapperProvider#getLoader()
*/
@Override
public List<ILoader<?, ?>> getLoader() throws GkException {
List<ILoader<?, ?>> loaders = new ArrayList<ILoader<?, ?>>();
loaders.add(new XmlGCodeMacroLoader());
loaders.add(new XmlGCodeMacroReferenceLoader(gcodeMacroService));
return loaders;
}
/** (inheritDoc)
* @see org.goko.core.workspace.service.IMapperProvider#getExporter()
*/
@Override
public List<IExporter<?, ?>> getExporter() throws GkException {
List<IExporter<?, ?>> exporters = new ArrayList<IExporter<?, ?>>();
exporters.add(new XmlGCodeMacroExporter());
exporters.add(new XmlGCodeMacroReferenceExporter());
return exporters;
}
}