blob: dd79434c1881a035020d23226cc0211be66631f6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2011 Brock Janiczak and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Brock Janiczak - initial API and implementation
* Tasktop Technologies - improvements
*******************************************************************************/
package org.eclipse.mylyn.internal.context.core;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Locale;
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.context.core.IInteractionContext;
import org.eclipse.mylyn.monitor.core.InteractionEvent;
import org.xml.sax.Attributes;
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;
import org.xml.sax.helpers.AttributesImpl;
/**
* @author Brock Janiczak
* @author Mik Kersten (refactoring)
*/
public class SaxContextWriter implements IInteractionContextWriter {
private OutputStream outputStream;
public void setOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
}
public void writeContextToStream(IInteractionContext context) throws IOException {
if (outputStream == null) {
IOException ioe = new IOException("OutputStream not set"); //$NON-NLS-1$
throw ioe;
}
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(new SAXSource(new SaxWriter(), new InteractionContextInputSource(context)),
new StreamResult(outputStream));
} catch (TransformerException e) {
StatusHandler.log(new Status(IStatus.ERROR, ContextCorePlugin.ID_PLUGIN, "Could not write context", e)); //$NON-NLS-1$
throw new IOException(e.getMessage());
}
}
private static class InteractionContextInputSource extends InputSource {
private final IInteractionContext context;
public InteractionContextInputSource(IInteractionContext context) {
this.context = context;
}
public IInteractionContext getContext() {
return this.context;
}
}
private class SaxWriter implements XMLReader {
private ContentHandler 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 = handler;
}
public ContentHandler getContentHandler() {
return handler;
}
public void setErrorHandler(ErrorHandler handler) {
this.errorHandler = handler;
}
public ErrorHandler getErrorHandler() {
return errorHandler;
}
public void parse(InputSource input) throws IOException, SAXException {
if (!(input instanceof InteractionContextInputSource)) {
throw new SAXException("Can only parse writable input sources"); //$NON-NLS-1$
}
IInteractionContext context = ((InteractionContextInputSource) input).getContext();
handler.startDocument();
AttributesImpl rootAttributes = new AttributesImpl();
rootAttributes.addAttribute("", InteractionContextExternalizer.ATR_ID, //$NON-NLS-1$
InteractionContextExternalizer.ATR_ID, "", context.getHandleIdentifier()); //$NON-NLS-1$
if (context.getContentLimitedTo() != null) {
rootAttributes.addAttribute("", SaxContextContentHandler.ATTRIBUTE_CONTENT, //$NON-NLS-1$
SaxContextContentHandler.ATTRIBUTE_CONTENT, "", context.getContentLimitedTo()); //$NON-NLS-1$
}
rootAttributes.addAttribute("", InteractionContextExternalizer.ATR_VERSION, //$NON-NLS-1$
InteractionContextExternalizer.ATR_VERSION, "", "1"); //$NON-NLS-1$ //$NON-NLS-2$
handler.startElement("", InteractionContextExternalizer.ELMNT_INTERACTION_HISTORY, //$NON-NLS-1$
InteractionContextExternalizer.ELMNT_INTERACTION_HISTORY, rootAttributes);
// List could get modified as we're writing
for (InteractionEvent ie : context.getInteractionHistory()) {
Attributes ieAttributes = createEventAttributes(ie);
handler.startElement("", SaxContextContentHandler.ATTRIBUTE_INTERACTION_EVENT, //$NON-NLS-1$
SaxContextContentHandler.ATTRIBUTE_INTERACTION_EVENT, ieAttributes);
handler.endElement("", SaxContextContentHandler.ATTRIBUTE_INTERACTION_EVENT, //$NON-NLS-1$
SaxContextContentHandler.ATTRIBUTE_INTERACTION_EVENT);
}
handler.endElement("", InteractionContextExternalizer.ELMNT_INTERACTION_HISTORY, //$NON-NLS-1$
InteractionContextExternalizer.ELMNT_INTERACTION_HISTORY);
handler.endDocument();
}
public void parse(String systemId) throws IOException, SAXException {
throw new SAXException("Can only parse writable input sources"); //$NON-NLS-1$
}
}
@SuppressWarnings({ "deprecation", "restriction" })
private Attributes createEventAttributes(InteractionEvent ie) {
SimpleDateFormat dateFormat = new SimpleDateFormat(InteractionContextExternalizer.DATE_FORMAT_STRING,
Locale.ENGLISH);
AttributesImpl ieAttributes = new AttributesImpl();
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_DELTA, //$NON-NLS-1$
InteractionContextExternalizer.ATR_DELTA, "", //$NON-NLS-1$
org.eclipse.mylyn.internal.commons.core.XmlStringConverter.convertToXmlString(ie.getDelta()));
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_END_DATE, //$NON-NLS-1$
InteractionContextExternalizer.ATR_END_DATE, "", dateFormat.format(ie.getEndDate())); //$NON-NLS-1$
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_INTEREST, //$NON-NLS-1$
InteractionContextExternalizer.ATR_INTEREST, "", Float.toString(ie.getInterestContribution())); //$NON-NLS-1$
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_KIND, InteractionContextExternalizer.ATR_KIND, //$NON-NLS-1$
"", ie.getKind().toString()); //$NON-NLS-1$
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_NAVIGATION, //$NON-NLS-1$
InteractionContextExternalizer.ATR_NAVIGATION, "", //$NON-NLS-1$
org.eclipse.mylyn.internal.commons.core.XmlStringConverter.convertToXmlString(ie.getNavigation()));
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_ORIGIN_ID, //$NON-NLS-1$
InteractionContextExternalizer.ATR_ORIGIN_ID, "", //$NON-NLS-1$
org.eclipse.mylyn.internal.commons.core.XmlStringConverter.convertToXmlString(ie.getOriginId()));
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_START_DATE, //$NON-NLS-1$
InteractionContextExternalizer.ATR_START_DATE, "", dateFormat.format(ie.getDate())); //$NON-NLS-1$
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_STRUCTURE_HANDLE, //$NON-NLS-1$
InteractionContextExternalizer.ATR_STRUCTURE_HANDLE, "", //$NON-NLS-1$
org.eclipse.mylyn.internal.commons.core.XmlStringConverter.convertToXmlString(ie.getStructureHandle()));
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_STRUCTURE_KIND, //$NON-NLS-1$
InteractionContextExternalizer.ATR_STRUCTURE_KIND, "", //$NON-NLS-1$
org.eclipse.mylyn.internal.commons.core.XmlStringConverter.convertToXmlString(ie.getStructureKind()));
if (ie instanceof AggregateInteractionEvent) {
// keep the state of the element (how it was collapsed and when it was created) to ensure that the context is the same after writing
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_NUM_EVENTS, //$NON-NLS-1$
InteractionContextExternalizer.ATR_NUM_EVENTS, "", //$NON-NLS-1$
Integer.toString(((AggregateInteractionEvent) ie).getNumCollapsedEvents()));
ieAttributes.addAttribute("", InteractionContextExternalizer.ATR_CREATION_COUNT, //$NON-NLS-1$
InteractionContextExternalizer.ATR_CREATION_COUNT, "", //$NON-NLS-1$
Integer.toString(((AggregateInteractionEvent) ie).getEventCountOnCreation()));
}
return ieAttributes;
}
}