/**
*
*/
package org.korsakow.services.export.task;
import java.awt.Font;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.dsrg.soenea.domain.MapperException;
import org.korsakow.domain.EventFactory;
import org.korsakow.domain.KeywordFactory;
import org.korsakow.domain.Media;
import org.korsakow.domain.PredicateFactory;
import org.korsakow.domain.RuleFactory;
import org.korsakow.domain.TriggerFactory;
import org.korsakow.domain.interf.IDynamicProperties;
import org.korsakow.domain.interf.IEvent;
import org.korsakow.domain.interf.IImage;
import org.korsakow.domain.interf.IInterface;
import org.korsakow.domain.interf.IKeyword;
import org.korsakow.domain.interf.IMedia;
import org.korsakow.domain.interf.IPredicate;
import org.korsakow.domain.interf.IProject;
import org.korsakow.domain.interf.IResource;
import org.korsakow.domain.interf.IRule;
import org.korsakow.domain.interf.ISnu;
import org.korsakow.domain.interf.ISound;
import org.korsakow.domain.interf.IText;
import org.korsakow.domain.interf.ITrigger;
import org.korsakow.domain.interf.IVideo;
import org.korsakow.domain.interf.IWidget;
import org.korsakow.ide.Build;
import org.korsakow.ide.DataRegistry;
import org.korsakow.ide.lang.LanguageBundle;
import org.korsakow.ide.resources.PredicateType;
import org.korsakow.ide.resources.TriggerType;
import org.korsakow.ide.rules.RuleType;
import org.korsakow.ide.task.AbstractTask;
import org.korsakow.ide.task.TaskException;
import org.korsakow.ide.util.DomUtil;
import org.korsakow.ide.util.FileUtil;
import org.korsakow.ide.util.Util;
import org.korsakow.services.export.ExportException;
import org.korsakow.services.export.Exporter;
import org.korsakow.services.plugin.predicate.IArgumentInfo;
import org.korsakow.services.plugin.predicate.IPredicateTypeInfo;
import org.korsakow.services.plugin.predicate.PredicateTypeInfoFactory;
import org.korsakow.services.plugin.rule.IRuleTypeInfo;
import org.korsakow.services.plugin.rule.RuleTypeInfoFactory;
import org.korsakow.services.util.ColorFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class XMLExportTask extends AbstractTask
{
@Deprecated
private static class MyDynamicProperties implements IDynamicProperties
{
private String id;
private Object value;
public MyDynamicProperties() {
}
public MyDynamicProperties(String id, Object value) {
this.id = id;
this.value = value;
}
public Object getDynamicProperty(String id) {
return value;
}
public Collection<String> getDynamicPropertyIds() {
if (id == null) return Collections.emptyList();
return Arrays.asList(id);
}
public void setDynamicProperty(String id, Object value) {
throw new IllegalStateException();
}
}
private final Collection<IVideo> videosToExport;// = new HashSet<IVideo>();
private final Collection<ISound> soundsToExport;// = new HashSet<ISound>();
private final Collection<IImage> imagesToExport;// = new HashSet<IImage>();
private final Collection<IText> textsToExport;// = new HashSet<Text>();
private final Collection<IInterface> interfacesToExport;// = new HashSet<IInterface>();;
private final Collection<ISnu> snusToExport;// = new HashSet<ISnu>();
private final Collection<Font> fontsToExport;
private final IProject project;
private final File rootDir;
private final String dataPath;
private final Map<String, String> filenamemap;
public XMLExportTask(String dataPath, IProject project, Collection<ISnu> snusToExport, Collection<IText> textsToExport, Collection<IImage> imagesToExport, Collection<ISound> soundsToExport, Collection<IVideo> videosToExport, Collection<IInterface> interfacesToExport, Collection<Font> fontsToExport, File rootDir, Map<String, String> filenamemap)
// public XMLExportTask(IProject project, Collection<ISnu> snusToExport, Collection<IInterface> interfacesToExport, File rootDir)
{
this.dataPath = dataPath;
this.videosToExport = videosToExport;
this.soundsToExport = soundsToExport;
this.imagesToExport = imagesToExport;
this.textsToExport = textsToExport;
this.snusToExport = snusToExport;
this.interfacesToExport = interfacesToExport;
this.fontsToExport = fontsToExport;
this.project = project;
this.rootDir = rootDir;
this.filenamemap = filenamemap;
}
@Override
public String getTitleString()
{
return LanguageBundle.getString("export.task.xml");
}
@Override
public void runTask() throws TaskException
{
Document doc;
try {
doc = projectToDOM(project, snusToExport, textsToExport, imagesToExport, soundsToExport, videosToExport, interfacesToExport);
DomUtil.writeDomXML(doc, new File(rootDir, dataPath));
} catch (ExportException e) {
throw new TaskException(e);
} catch (IOException e) {
throw new TaskException(e);
} catch (TransformerException e) {
throw new TaskException(e);
} catch (DOMException e) {
throw new TaskException(e);
} catch (MapperException e) {
throw new TaskException(e);
}
}
private static Element keywordsToDom(Document doc, Collection<IKeyword> keywords, String extraKeyword)
{
TreeSet<IKeyword> set = new TreeSet<IKeyword>(keywords); // treeset sorts them "naturally"
Element elm = doc.createElement("keywords");
if (extraKeyword != null)
set.add(KeywordFactory.createNew(extraKeyword));
for (IKeyword keyword : set) {
DomUtil.appendTextNode(doc, elm, "Keyword", keyword.getValue());
}
return elm;
}
private static void dynamicPropertiesToDom(Document doc, Element elm, IDynamicProperties absprops)
{
for (String id : absprops.getDynamicPropertyIds())
DomUtil.appendTextNode(doc, elm, id, absprops.getDynamicProperty(id));
}
private static void dynamicPropertiesToDom(Document doc, Element elm, IRule rule) throws MapperException
{
IRuleTypeInfo typeInfo = RuleTypeInfoFactory.getFactory().getTypeInfo(rule.getRuleType());
for (String id : rule.getDynamicPropertyIds()) {
IArgumentInfo argInfo = typeInfo.getArgument(id);
String value = argInfo.serialize(rule.getDynamicProperty(id));
DomUtil.appendTextNode(doc, elm, id, value);
}
}
private static void dynamicPropertiesToDom(Document doc, Element elm, IPredicate pred) throws MapperException
{
IPredicateTypeInfo typeInfo = PredicateTypeInfoFactory.getFactory().getTypeInfo(pred.getPredicateType());
for (String id : pred.getDynamicPropertyIds()) {
IArgumentInfo argInfo = typeInfo.getArgument(id);
String value = argInfo.serialize(pred.getDynamicProperty(id));
DomUtil.appendTextNode(doc, elm, id, value);
}
}
@Deprecated
private static Element ruleToDomDepricated(Document doc, IRule rule) throws MapperException
{
Element elm = doc.createElement("Rule");
elm.appendChild(doc.createComment(rule.getRuleType()));
DomUtil.appendTextNode(doc, elm, "id", rule.getId());
DomUtil.appendTextNode(doc, elm, "type", rule.getRuleType());
dynamicPropertiesToDom(doc, elm, rule);
DomUtil.setString(doc, elm, "triggerType", null); // kind of hack, Triggers are not yet properly implemented
Element rulesNode = doc.createElement("rules");
elm.appendChild(rulesNode);
for (IRule subrule : rule.getRules()) {
rulesNode.appendChild(ruleToDomDepricated(doc, subrule));
}
elm.appendChild(keywordsToDom(doc, rule.getKeywords(), null));
return elm;
}
private static Element triggerToDom(Document doc, long id, String type, IDynamicProperties dynamicProperties)
{
Element elm = doc.createElement("Trigger");
DomUtil.appendTextNode(doc, elm, "id", id);
DomUtil.appendTextNode(doc, elm, "type", type);
dynamicPropertiesToDom(doc, elm, dynamicProperties);
return elm;
}
private static Element predicateToDom(Document doc, long id, String type, IPredicate dynamicProperties, List<IPredicate> predicates) throws MapperException
{
Element elm = doc.createElement("Predicate");
DomUtil.appendTextNode(doc, elm, "id", id);
DomUtil.appendTextNode(doc, elm, "type", type);
if (dynamicProperties != null) // TODO: depricated check, needed until Snu.rules is eliminated
dynamicPropertiesToDom(doc, elm, dynamicProperties);
Element predicatesNode = doc.createElement("predicates");
elm.appendChild(predicatesNode);
for (IPredicate sub : predicates) {
predicatesNode.appendChild(predicateToDom(doc, sub.getId(), sub.getPredicateType(), sub, sub.getPredicates()));
}
return elm;
}
private static Element ruleToDom(Document doc, long id, String type, Collection<IKeyword> keywords, IRule dynamicProperties, List<IRule> rules) throws MapperException
{
Element elm = doc.createElement("Rule");
DomUtil.appendTextNode(doc, elm, "id", id);
DomUtil.appendTextNode(doc, elm, "type", type);
dynamicPropertiesToDom(doc, elm, dynamicProperties);
elm.appendChild(keywordsToDom(doc, keywords, null));
Element rulesNode = doc.createElement("rules");
elm.appendChild(rulesNode);
if (RuleType.Search.getId().equals(type)) {
boolean clearLinks = false;
for (IRule sub : rules) {
if (RuleType.ClearScores.getId().equals(sub.getRuleType())) {
clearLinks = true;
break;
}
}
DomUtil.appendBooleanNode(doc, elm, "keepLinks", !clearLinks);
}
for (IRule sub : rules) {
if (RuleType.ClearScores.getId().equals(sub.getRuleType())) {
continue;
}
rulesNode.appendChild(ruleToDom(doc, sub.getId(), sub.getRuleType(), sub.getKeywords(), sub, sub.getRules()));
}
return elm;
}
private static Element eventToDom(Document doc, long id, ITrigger trigger, IPredicate predicate, IRule rule) throws DOMException, MapperException
{
Element elm = doc.createElement("Event");
DomUtil.appendTextNode(doc, elm, "id", id);
elm.appendChild(triggerToDom(doc, trigger.getId(), trigger.getTriggerType(), trigger));
elm.appendChild(predicateToDom(doc, predicate.getId(), predicate.getPredicateType(), predicate, predicate.getPredicates()));
elm.appendChild(ruleToDom(doc, rule.getId(), rule.getRuleType(), rule.getKeywords(), rule, rule.getRules()));
return elm;
}
private static Element widgetToDom(Document doc, IWidget widget) throws ExportException
{
Element elm = doc.createElement("Widget");
DomUtil.appendTextNode(doc, elm, "id", widget.getId());
if (widget.getId() == null)
throw new ExportException(new NullPointerException(), null);
DomUtil.appendTextNode(doc, elm, "type", widget.getWidgetId());
Element persist = doc.createElement("persist");
DomUtil.appendTextNode(doc, persist, "condition", widget.getPersistCondition().getId());
DomUtil.appendTextNode(doc, persist, "action", widget.getPersistAction().getId());
elm.appendChild(persist);
DomUtil.appendNumberNode(doc, elm, "x", widget.getX());
DomUtil.appendNumberNode(doc, elm, "y", widget.getY());
DomUtil.appendNumberNode(doc, elm, "width", widget.getWidth());
DomUtil.appendNumberNode(doc, elm, "height", widget.getHeight());
dynamicPropertiesToDom(doc, elm, widget);
elm.appendChild(keywordsToDom(doc, widget.getKeywords(), widget.getName()));
return elm;
}
private static void resourceToDom(Document doc, IResource resource, Element elm)
{
DomUtil.appendTextNode(doc, elm, "id", resource.getId());
DomUtil.appendTextNode(doc, elm, "name", resource.getName());
elm.appendChild(keywordsToDom(doc, resource.getKeywords(), resource.getName()));
}
private Element videoToDom(Document doc, IVideo video) throws IOException
{
Element elm = doc.createElement("Video");
resourceToDom(doc, video, elm);
String filename = getExportFilename(video.getAbsoluteFilename());
DomUtil.appendTextNode(doc, elm, "filename", formatExportUrl(filename));
if (video.getSubtitles() != null) {
String subtitlefilename = getExportFilename(Media.getAbsoluteFilename(video.getSubtitles()));
DomUtil.appendTextNode(doc, elm, "subtitles", formatExportUrl(subtitlefilename));
}
return elm;
}
private Element textToDom(Document doc, IText text) throws IOException
{
Element elm = doc.createElement("Text");
resourceToDom(doc, text, elm);
switch (text.getSource())
{
case INLINE:
DomUtil.appendTextNode(doc, elm, "text", text.getText());
break;
case FILE:
String filename = getExportFilename(text.getAbsoluteFilename());
DomUtil.appendTextNode(doc, elm, "filename", formatExportUrl(filename));
break;
}
return elm;
}
private Element imageToDom(Document doc, IImage image) throws IOException
{
Element elm = doc.createElement("Image");
resourceToDom(doc, image, elm);
String filename = getExportFilename(image.getAbsoluteFilename());
DomUtil.appendTextNode(doc, elm, "filename", formatExportUrl(filename));
DomUtil.appendNumberNode(doc, elm, "duration", image.getDuration());
return elm;
}
private Element soundToDom(Document doc, ISound sound) throws IOException
{
Element elm = doc.createElement("Sound");
resourceToDom(doc, sound, elm);
String filename = FileUtil.setFileExtension(sound.getFilename(), FileUtil.getFileExtension(Exporter.SOUND_EXPORT_FORMAT));
filename = getExportFilename(sound.getAbsoluteFilename());
DomUtil.appendTextNode(doc, elm, "filename", formatExportUrl(filename));
if (sound.getSubtitles() != null) {
String subtitlefilename = getExportFilename(Media.getAbsoluteFilename(sound.getSubtitles()));
DomUtil.appendTextNode(doc, elm, "subtitles", formatExportUrl(subtitlefilename));
}
return elm;
}
private static Element interfaceToDom(Document doc, IInterface interf) throws ExportException
{
Element elm = doc.createElement("Interface");
resourceToDom(doc, interf, elm);
if (interf.getClickSound()!=null) {
DomUtil.appendTextNode(doc, elm, "clickSoundId", interf.getClickSound().getId());
DomUtil.appendNumberNode(doc, elm, "clickSoundVolume", interf.getClickSoundVolume());
}
if (interf.getBackgroundImage()!=null) {
DomUtil.appendTextNode(doc, elm, "backgroundImageId", interf.getBackgroundImage().getId());
}
if (interf.getBackgroundColor()!=null) {
DomUtil.appendTextNode(doc, elm, "backgroundColor", ColorFactory.toString(interf.getBackgroundColor()));
}
Element widgetsNode = doc.createElement("widgets");
elm.appendChild(widgetsNode);
Collection<IWidget> widgets = interf.getWidgets();
for (IWidget widget : widgets)
widgetsNode.appendChild(widgetToDom(doc, widget));
return elm;
}
private static Element snuToDom(Document doc, ISnu snu) throws ExportException, DOMException, MapperException
{
Element elm = doc.createElement("Snu");
resourceToDom(doc, snu, elm);
// if (snu.getIVideo()!=null)
if (snu.getThumbnail() != null)
DomUtil.appendTextNode(doc, elm, "thumbnailId", snu.getThumbnail().getId());
DomUtil.appendTextNode(doc, elm, "mainMediaId", snu.getMainMedia().getId());
DomUtil.appendNumberNode(doc, elm, "rating", snu.getRating());
DomUtil.appendNumberNode(doc, elm, "lives", snu.getLives(), "NaN");
DomUtil.appendNumberNode(doc, elm, "maxLinks", snu.getMaxLinks(), "NaN");
DomUtil.appendBooleanNode(doc, elm, "looping", snu.getLooping());
DomUtil.appendBooleanNode(doc, elm, "starter", snu.getStarter());
DomUtil.appendBooleanNode(doc, elm, "ender", snu.getEnder());
if (snu.getBackgroundSound()!=null) {
DomUtil.appendTextNode(doc, elm, "backgroundSoundId", snu.getBackgroundSound().getId());
DomUtil.appendNumberNode(doc, elm, "backgroundSoundVolume", snu.getBackgroundSoundVolume());
}
DomUtil.appendTextNode(doc, elm, "backgroundSoundMode", snu.getBackgroundSoundMode().getId());
DomUtil.appendBooleanNode(doc, elm, "backgroundSoundLooping", snu.getBackgroundSoundLooping());
Element eventsNode = doc.createElement("events");
elm.appendChild(eventsNode);
for (IEvent event : snu.getEvents()) {
eventsNode.appendChild(eventToDom(doc, event.getId(), event.getTrigger(), event.getPredicate(), event.getRule()));
}
for (final IRule rule : snu.getRules()) {
Element eventElm = doc.createElement("Event");
DomUtil.appendTextNode(doc, eventElm, "id", DataRegistry.getMaxId());
eventElm.appendChild(triggerToDom(doc, DataRegistry.getMaxId(), TriggerType.SnuTime.getId(), new MyDynamicProperties("time", rule.getTriggerTime())));
eventElm.appendChild(predicateToDom(doc, DataRegistry.getMaxId(), PredicateType.True.getId(), null, Util.list(IPredicate.class)));
eventElm.appendChild(ruleToDom(doc, rule.getId(), rule.getRuleType(), rule.getKeywords(), rule, rule.getRules()));
eventsNode.appendChild(eventElm);
}
if (snu.getInterface()==null) {
//TODO: Stu: this should throw some other form of exception which is caught and wrapped above
throw new ExportException("SNU " + snu.getName() + "; " + LanguageBundle.getString("export.errors.snuhasnointerface"), null);
}
DomUtil.appendTextNode(doc, elm, "interfaceId", snu.getInterface().getId());
if (snu.getPreviewMedia()!=null)
DomUtil.appendTextNode(doc, elm, "previewMediaId", snu.getPreviewMedia().getId());
DomUtil.appendTextNode(doc, elm, "previewText", snu.getPreviewText());
DomUtil.appendTextNode(doc, elm, "insertText", snu.getInsertText());
return elm;
}
private Document projectToDOM(IProject project,
Collection<ISnu> snusToExport,
Collection<IText> textsToExport,
Collection<IImage> imagesToExport,
Collection<ISound> soundsToExport,
Collection<IVideo> videosToExport,
Collection<IInterface> interfacesToExport) throws ExportException, IOException, DOMException, MapperException
{
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
try {
docBuilder = dbfac.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new ExportException(e, rootDir);
}
Document doc = docBuilder.newDocument();
Element root = doc.createElement("korsakow");
doc.appendChild(root);
root.setAttribute("versionMajor", Build.getVersion());
root.setAttribute("versionMinor", ""+Build.getRelease());
Element projNode = doc.createElement("Project");
root.appendChild(projNode);
resourceToDom(doc, project, projNode);
DomUtil.appendTextNode(doc, projNode, "uuid", project.getUUID());
// if (project.getMovieWidth() != null)
DomUtil.appendNumberNode(doc, projNode, "movieWidth", project.getMovieWidth());
// if (project.getMovieHeight() != null)
DomUtil.appendNumberNode(doc, projNode, "movieHeight", project.getMovieHeight());
if (project.getBackgroundSound()!=null) {
DomUtil.appendTextNode(doc, projNode, "backgroundSoundId", project.getBackgroundSound().getId());
DomUtil.appendNumberNode(doc, projNode, "backgroundSoundVolume", project.getBackgroundSoundVolume());
DomUtil.appendBooleanNode(doc, projNode, "backgroundSoundLooping", project.getBackgroundSoundLooping());
}
if (project.getClickSound()!=null) {
DomUtil.appendTextNode(doc, projNode, "clickSoundId", project.getClickSound().getId());
DomUtil.appendNumberNode(doc, projNode, "clickSoundVolume", project.getClickSoundVolume());
}
if (project.getSplashScreenMedia()!=null) {
DomUtil.appendTextNode(doc, projNode, "splashScreenMediaId", project.getSplashScreenMedia().getId());
}
DomUtil.appendBooleanNode(doc, projNode, "randomLinkMode", project.getRandomLinkMode());
DomUtil.appendBooleanNode(doc, projNode, "keepLinksOnEmptySearch", project.getKeepLinksOnEmptySearch());
DomUtil.appendNumberNode(doc, projNode, "maxLinks", project.getMaxLinks(), "NaN");
List<IEvent> events = new ArrayList<IEvent>();
if (project.getBackgroundImage() != null) {
DomUtil.appendTextNode(doc, projNode, "backgroundImageId", project.getBackgroundImage().getId());
ITrigger trigger = TriggerFactory.createClean(TriggerType.Initialized.getId());
IPredicate pred = PredicateFactory.createClean(PredicateType.True.getId());
IRule rule = RuleFactory.createClean(RuleType.SetBackgroundImage.getId());
rule.setDynamicProperty("imageId", project.getBackgroundImage().getId());
IEvent event = EventFactory.createClean(trigger, pred, rule);
events.add(event);
}
if (project.getBackgroundColor()!=null) {
DomUtil.appendTextNode(doc, projNode, "backgroundColor", ColorFactory.toString(project.getBackgroundColor()));
}
Element eventsNode = doc.createElement("events");
projNode.appendChild(eventsNode);
for (IEvent event : events) {
eventsNode.appendChild(eventToDom(doc, event.getId(), event.getTrigger(), event.getPredicate(), event.getRule()));
}
Element snusNode = doc.createElement("snus");
root.appendChild(snusNode);
for (ISnu snu : snusToExport) {
try {
validate(snu);
snusNode.appendChild(snuToDom(doc, snu));
} catch (ExportException e) {
//Hack because the export Exception is thrown in a static method that
//has no reason to know of the root dir.
//TODO: Stu: this should throw some other form of Exception which is caught and converted.
e.setProjectFile(rootDir);
throw e;
}
}
Element interfsNode = doc.createElement("interfaces");
root.appendChild(interfsNode);
for (IInterface interf : interfacesToExport) {
try {
interfsNode.appendChild(interfaceToDom(doc, interf));
} catch (ExportException e) {
//Hack because the export Exception is thrown in a static method that
//has no reason to know of the root dir.
//TODO: Stu: this should throw some other form of Exception which is caught and converted.
e.setProjectFile(rootDir);
throw e;
}
}
Element textsNode = doc.createElement("texts");
root.appendChild(textsNode);
for (IText text : textsToExport) {
try {
validate(text);
} catch (ExportException e) {
//Hack because the export Exception is thrown in a static method that
//has no reason to know of the root dir.
//TODO: Stu: this should throw some other form of Exception which is caught and converted.
e.setProjectFile(rootDir);
throw e;
}
textsNode.appendChild(textToDom(doc, text));
}
Element videosNode = doc.createElement("videos");
root.appendChild(videosNode);
for (IVideo video : videosToExport) {
validate(video);
videosNode.appendChild(videoToDom(doc, video));
}
Element soundsNode = doc.createElement("sounds");
root.appendChild(soundsNode);
for (ISound sound : soundsToExport) {
validate(sound);
soundsNode.appendChild(soundToDom(doc, sound));
}
Element imagesNode = doc.createElement("images");
root.appendChild(imagesNode);
for (IImage image : imagesToExport) {
validate(image);
imagesNode.appendChild(imageToDom(doc, image));
}
Element fontsNode = doc.createElement("fonts");
root.appendChild(fontsNode);
if (!fontsToExport.isEmpty()) {
String fontfilename = getExportFilename(new File(Exporter.FONT_DIR, "font.swf").getPath());
DomUtil.appendTextNode(doc, fontsNode, "Font", formatExportUrl(fontfilename));
}
return doc;
}
private static void validate(IMedia media) throws ExportException
{
switch (media.getSource())
{
case FILE:
if (media.getFilename() == null)
throw new ExportException("media has null filename: " + media.getName(), null);
if (media.getFilename().length()==0)
throw new ExportException("media has empty filename:" + media.getName(), null);
File file = null;
try {
file = new File(media.getAbsoluteFilename());
} catch (FileNotFoundException e) {
throw new ExportException(e, null);
}
if (!file.exists() || !file.canRead())
throw new ExportException("file not found or cannot read: " + file.getAbsolutePath(), null);
break;
case INLINE:
break;
default:
throw new ExportException("invalid source: " + media.getSource(), null);
}
}
private static void validate(ISnu snu) throws ExportException
{
IMedia media = snu.getMainMedia();
if (media == null)
throw new ExportException("SNU has no video", null);
validate(media);
}
/**
* URL encodes the elements of the path as Per URLEncoder, however we ensure this is done
* for all entities, e.g. space encoded as %20, not +
* Path separators are not encoded.
*
* This is sometimes necessary for being able to view files on the hard drive in the browser
* @throws UnsupportedEncodingException
*/
public static String formatExportUrl(String filename) throws UnsupportedEncodingException
{
String[] pathparts = filename.split("[/\\\\]");
StringBuilder sb = new StringBuilder();
for (String part : pathparts)
{
String encoded = URLEncoder.encode(part, "UTF-8");
encoded = encoded.replace("+", "%20");
sb.append(encoded)
.append('/');
}
sb.deleteCharAt(sb.length()-1); // final '/'
filename = sb.toString();
return filename;
}
private String getExportFilename(String mediafilename) throws IOException
{
if (filenamemap.containsKey(mediafilename))
return filenamemap.get(mediafilename);
throw new IOException("Filename not in map: " + mediafilename);
}
}