/*******************************************************************************
* Copyright (c) 2006-2007 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* IBM Research
*******************************************************************************/
package com.ibm.research.tours.serializer;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.XMLMemento;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
import com.ibm.research.tours.ITimeLimit;
import com.ibm.research.tours.ITourElement;
import com.ibm.research.tours.TimeLimit;
import com.ibm.research.tours.ToursPlugin;
public class TourSerializer
{
public static final String TOUR_ROOT = "tour";
public static final String TITLE = "title";
public static final String DESCRIPTION = "description";
public static final String AUTHOR = "author";
public static final String ELEMENTS = "tour-elements";
public static final String ELEMENT = "element";
public static final String TYPE = "type";
public static final String TIME_LIMIT_ELEMENT = "time-limit";
public static final String MINUTES_ELEMENT = "minutes";
public static final String SECONDS_ELEMENT = "seconds";
private static final String TOUR_ID = "id";
/**
* Create a tour memento based on the given tour
* @param tour
* @return
*/
private static XMLMemento createTourMemento(XMLTour tour)
{
XMLMemento memento = XMLMemento.createWriteRoot(TOUR_ROOT);
memento.putString(TOUR_ID, tour.getID());
/**
* Load the base elements
*/
IMemento title = memento.createChild(TITLE);
title.putTextData(tour.getTitle());
IMemento description = memento.createChild(DESCRIPTION);
description.putTextData(tour.getDescription());
IMemento author = memento.createChild(AUTHOR);
author.putTextData(tour.getAuthor());
if(tour.getTimeLimit() != null)
{
IMemento timeLimitMemento = memento.createChild(TIME_LIMIT_ELEMENT);
IMemento minutesMemento = timeLimitMemento.createChild(MINUTES_ELEMENT);
minutesMemento.putTextData(Integer.toString(tour.getTimeLimit().getMinutes()));
IMemento secondsMemento = timeLimitMemento.createChild(SECONDS_ELEMENT);
secondsMemento.putTextData(Integer.toString(tour.getTimeLimit().getSeconds()));
}
IMemento elementsMemento = memento.createChild(ELEMENTS);
if(tour.getElementCount() > 0)
{
for(ITourElement element : tour.getElements())
{
// Create an element memento
IMemento elementMemento = elementsMemento.createChild(ELEMENT);
String className = element.getClass().getName();
ClassLoader elementClassLoader = element.getClass().getClassLoader();
if (elementClassLoader instanceof BundleReference) {
Bundle bundle = ((BundleReference)elementClassLoader).getBundle();
String bundleName = bundle.getSymbolicName();
className = bundleName + ":" + className;
}
// Write the type
elementMemento.putString(TYPE, className);
// Let the element do its thing
element.save(elementMemento);
}
}
return memento;
}
private static void writeMemento(IFile file, XMLMemento memento) throws IOException, CoreException
{
if(file !=null)
{
// Write to a string
StringWriter writer = new StringWriter();
memento.save(writer);
// Create the input stream
ByteArrayInputStream bais = new ByteArrayInputStream(writer.getBuffer().toString().getBytes());
file.setContents(bais, true, false, null);
writer.close();
}
}
// TODO progress monitor and error handling
public static void write(IFile file, XMLTour tour) throws Exception
{
XMLMemento memento = createTourMemento(tour);
writeMemento(file,memento);
}
// TODO progress monitor and error handling
public static void read(IFile file, XMLTour tour) throws CoreException
{
InputStream input = file.getContents();
IMemento memento;
memento = XMLMemento.createReadRoot(new InputStreamReader(input));
// Populate the tour from the memento
readMemento(memento,tour);
}
private static void readMemento(IMemento memento, XMLTour tour)
{
tour.setID(memento.getString(TOUR_ID)); // overrides default ID
// Load the base elements
IMemento titleMemento = memento.getChild(TITLE);
String title = titleMemento.getTextData();
if(title != null)
tour.setTitle(title);
IMemento descriptionMemento = memento.getChild(DESCRIPTION);
String description = descriptionMemento.getTextData();
if(description != null)
tour.setDescription(description);
IMemento authorMemento = memento.getChild(AUTHOR);
String author = authorMemento.getTextData();
if(author != null)
tour.setAuthor(author);
IMemento timeLimitMemento = memento.getChild(TIME_LIMIT_ELEMENT);
if(timeLimitMemento!=null)
{
IMemento minutesMemento = timeLimitMemento.getChild(MINUTES_ELEMENT);
IMemento secondsMemento = timeLimitMemento.getChild(SECONDS_ELEMENT);
int minutes = -1;
int seconds = -1;
if(minutesMemento!=null)
{
String minuteString = minutesMemento.getTextData();
if(minuteString !=null)
{
try
{
minutes = Integer.parseInt(minuteString);
}
catch (NumberFormatException e)
{
e.printStackTrace();
}
}
}
if(secondsMemento!=null)
{
String secondString = secondsMemento.getTextData();
if(secondString !=null)
{
try
{
seconds = Integer.parseInt(secondString);
}
catch (NumberFormatException e)
{
e.printStackTrace();
}
}
}
if(minutes>0 || seconds > 0)
{
ITimeLimit limit = new TimeLimit();
if(minutes > 0)
limit.setMinutes(minutes);
if(seconds > 0)
limit.setSeconds(minutes);
tour.setTimeLimit(limit);
}
}
IMemento elementsMemento = memento.getChild(ELEMENTS);
if(elementsMemento != null)
{
IMemento[] elementMementos = elementsMemento.getChildren(ELEMENT);
Vector<ITourElement> newElements = new Vector<ITourElement>();
for(IMemento elementMemento : elementMementos)
{
String type = elementMemento.getString(TYPE);
ITourElement element = null;
if(type != null)
{
try
{
Bundle bundle = ToursPlugin.getDefault().getBundle();
int bundleSeparator = type.indexOf(':');
if (bundleSeparator > 0) {
String bundleName = type.substring(0, bundleSeparator);
type = type.substring(bundleSeparator + 1);
Bundle typeBundle = Platform.getBundle(bundleName);
if (typeBundle != null) {
bundle = typeBundle;
}
}
Class<?> clazz = bundle.loadClass(type);
element = (ITourElement)clazz.newInstance();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
continue;
}
catch (InstantiationException e)
{
e.printStackTrace();
continue;
}
catch (IllegalAccessException e)
{
e.printStackTrace();
continue;
}
if(element != null)
{
// Load and add the element
element.load(elementMemento);
newElements.add(element);
}
}
}
if(newElements != null)
tour.addElements(newElements.toArray(new ITourElement[0]));
}
}
}