blob: a19277998e580e1e18ab7b4ede6d12f7f24ac522 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Tasktop Technologies and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.tasks.core.externalization;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants;
import org.eclipse.mylyn.internal.tasks.core.ITransferList;
import org.eclipse.mylyn.internal.tasks.core.SaxRepositoriesWriter;
import org.eclipse.mylyn.tasks.core.IRepositoryElement;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
/**
* Adapted from {@link SaxRepositoriesWriter}
*/
public class SaxTaskListWriter {
private static final String ATTRIBUTE_VERSION = "Version"; //$NON-NLS-1$
// Mylyn 3.0
private static final String VALUE_VERSION = "2.0"; //$NON-NLS-1$
private OutputStream outputStream;
public void setOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
}
public void writeTaskListToStream(ITransferList taskList, Document orphans) throws IOException {
if (outputStream == null) {
throw new IOException("OutputStream not set"); //$NON-NLS-1$
}
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new SAXSource(new TaskListWriter(), new TaskListInputSource(taskList, orphans)),
new StreamResult(outputStream));
} catch (TransformerException e) {
StatusHandler.log(new Status(IStatus.ERROR, ITasksCoreConstants.ID_PLUGIN, "Could not write task list", e)); //$NON-NLS-1$
throw new IOException(e.getMessage(), e);
}
}
private static class TaskListInputSource extends InputSource {
private final ITransferList taskList;
private final Document orphans;
public TaskListInputSource(ITransferList taskList, Document orphans) {
this.taskList = taskList;
this.orphans = orphans;
}
public ITransferList getTaskList() {
return this.taskList;
}
public Document getOrphans() {
return orphans;
}
}
private static class TaskListWriter implements XMLReader {
private ContentHandlerWrapper handler;
private ErrorHandler errorHandler;
public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
return false;
}
public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {
}
public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
return null;
}
public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
}
public void setEntityResolver(EntityResolver resolver) {
}
public EntityResolver getEntityResolver() {
return null;
}
public void setDTDHandler(DTDHandler handler) {
}
public DTDHandler getDTDHandler() {
return null;
}
public void setContentHandler(ContentHandler handler) {
this.handler = new ContentHandlerWrapper(handler);
}
public ContentHandler getContentHandler() {
return handler.getHandler();
}
public void setErrorHandler(ErrorHandler handler) {
this.errorHandler = handler;
}
public ErrorHandler getErrorHandler() {
return errorHandler;
}
public void parse(InputSource input) throws IOException, SAXException {
if (!(input instanceof TaskListInputSource)) {
throw new SAXException("Can only parse writable input sources"); //$NON-NLS-1$
}
TaskListInputSource taskListInputSource = (TaskListInputSource) input;
handler.getHandler().startDocument();
writeTaskList(taskListInputSource.getTaskList(), taskListInputSource.getOrphans());
handler.getHandler().endDocument();
}
private void writeTaskList(ITransferList taskList, Document orphanDocument) throws IOException, SAXException {
AttributesWrapper attributes = new AttributesWrapper();
attributes.addAttribute(ATTRIBUTE_VERSION, VALUE_VERSION);
handler.startElement(TaskListExternalizationConstants.NODE_TASK_LIST, attributes);
writeTaskListElements(new SaxTaskWriter(handler), taskList.getAllTasks());
writeTaskListElements(new SaxCategoryWriter(handler), taskList.getCategories());
writeTaskListElements(new SaxQueryWriter(handler), taskList.getQueries());
writeOrphans(orphanDocument);
handler.endElement(TaskListExternalizationConstants.NODE_TASK_LIST);
}
private <T extends IRepositoryElement> void writeTaskListElements(SaxTaskListElementWriter<T> writer,
Collection<T> elements) throws SAXException {
for (T element : elements) {
writer.writeElement(element);
}
if (!writer.getErrors().isOK()) {
StatusHandler.log(writer.getErrors());
}
}
private void writeOrphans(Document orphanDocument) throws SAXException {
if (orphanDocument != null) {
SaxOrphanWriter writer = new SaxOrphanWriter(handler);
NodeList orphanNodes = orphanDocument.getChildNodes();
if (orphanNodes.getLength() == 1) {
writer.writeOrphans(orphanNodes.item(0).getChildNodes());
}
}
}
public void parse(String systemId) throws IOException, SAXException {
throw new SAXException("Can only parse writable input sources"); //$NON-NLS-1$
}
}
}