/*
* Copyright 2013 Serdar.
*
* 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 de.fub.gpxmodule.actions;
import de.fub.gpxmodule.GPXDataObject;
import de.fub.gpxmodule.actions.ui.MergeForm;
import de.fub.gpxmodule.xml.Gpx;
import de.fub.gpxmodule.xml.ObjectFactory;
import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.filesystems.FileAlreadyLockedException;
import org.openide.filesystems.FileObject;
import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle.Messages;
import org.openide.util.RequestProcessor;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;
@ActionID(
category = "GPX",
id = "de.fub.maps.project.actions.GpxMergeAction")
@ActionRegistration(
// iconBase = "de/fub/gpxmodule/icons/gpxmerge.png",
displayName = "#CTL_GpxMergeAction", lazy = false)
@ActionReferences({
@ActionReference(path = "Menu/GPX", position = 0),
@ActionReference(path = "Toolbars/GPX", position = 0),
@ActionReference(path = "Loaders/text/gpx+xml/Actions", position = 210, separatorAfter = 250)
})
@Messages({"CTL_GpxMergeAction=Merge Gpx",
"CLT_Merge_Filename_Dialog_Message=Please specify a filename for the to be merged gpx file.",
"CLT_Merge_Filename_Dialog_Title=Gpx Merge Dialog",
"CLT_Merge_Procedure=Merging..."
})
public final class GpxMergeAction extends AbstractAction implements ContextAwareAction, LookupListener {
private static final long serialVersionUID = 1L;
private final Lookup context;
private Lookup.Result<GPXDataObject> result;
public GpxMergeAction() {
this(Utilities.actionsGlobalContext());
result = Utilities.actionsGlobalContext().lookupResult(GPXDataObject.class);
result.addLookupListener(WeakListeners.create(LookupListener.class, GpxMergeAction.this, result));
}
public GpxMergeAction(Lookup actionContext) {
super(Bundle.CTL_GpxMergeAction());
putValue("iconBase", "de/fub/gpxmodule/icons/gpxmerge.png");
this.context = actionContext;
setEnabled(this.context.lookupResult(GPXDataObject.class).allInstances().size() > 1);
}
@Override
public void actionPerformed(ActionEvent ev) {
final Collection<? extends GPXDataObject> allInstances = this.context.lookupResult(GPXDataObject.class).allInstances();
if (!allInstances.isEmpty()) {
FileObject parentFolder = allInstances.iterator().next().getPrimaryFile().getParent();
MergeForm mergeForm = new MergeForm(parentFolder);
DialogDescriptor descriptor = mergeForm.getDescriptor();
Dialog dialog = DialogDisplayer.getDefault().createDialog(descriptor);
dialog.setVisible(true);
if (mergeForm.checkIfValid()) {
synchronized (this) { // synchronization only because of wait method.
// need fileObject to merge to
String filename = mergeForm.getFilename().getText();
String foldername = mergeForm.getFoldername().getText();
try {
if (parentFolder.getFileObject(foldername) == null) {
parentFolder = parentFolder.createFolder(foldername);
} else {
parentFolder = parentFolder.getFileObject(foldername);
}
if (parentFolder.getFileObject(filename) == null) {
parentFolder = parentFolder.createData(filename);
try {
// need some time until the file lock is released
wait(200);
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);
}
}
final FileObject destFileObject = parentFolder;
RequestProcessor.getDefault().post(new Runnable() {
@Override
public void run() {
merge(allInstances, destFileObject);
}
});
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
}
}
}
private void merge(Collection<? extends GPXDataObject> list, FileObject destinationFileObject) {
Gpx gpx = new Gpx();
OutputStream outputStream = null;
ProgressHandle handle = ProgressHandleFactory.createHandle(Bundle.CLT_Merge_Procedure());
try {
handle.start(list.size());
int workunit = 0;
for (GPXDataObject dataObject : list) {
Gpx toMergeGpx = dataObject.getGpx();
gpx.getTrk().addAll(toMergeGpx.getTrk());
gpx.getRte().addAll(toMergeGpx.getRte());
gpx.getWpt().addAll(toMergeGpx.getWpt());
handle.progress(++workunit);
}
outputStream = destinationFileObject.getOutputStream();
javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(Gpx.class);
javax.xml.bind.Marshaller marshaller = jaxbCtx.createMarshaller();
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); //NOI18N
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(new ObjectFactory().createGpx(gpx), outputStream);
} catch (FileAlreadyLockedException ex) {
Exceptions.printStackTrace(ex);
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
} catch (javax.xml.bind.JAXBException ex) {
Exceptions.printStackTrace(ex);
} catch (Exception ex) {
Exceptions.printStackTrace(ex);
} finally {
handle.finish();
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
}
}
@Override
public Object getValue(String key) {
if (Action.LARGE_ICON_KEY.equals(key)) {
Logger.getLogger(getClass().getName()).info(key);
}
return super.getValue(key); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new GpxMergeAction(actionContext);
}
@Override
public void resultChanged(LookupEvent ev) {
if (result != null) {
Collection<? extends GPXDataObject> allInstances = result.allInstances();
setEnabled(allInstances.size() > 1);
}
}
}