blob: adcaf661bf8b5663a48666c2974fec0f60844ebb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 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:
* Daisuke SATO - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.ai.audio.description.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.Stack;
import org.eclipse.actf.ai.audio.description.IMetadata;
import org.eclipse.actf.ai.audio.description.IMetadataProvider;
import org.eclipse.actf.ai.xmlstore.IXMLInfo;
import org.eclipse.actf.ai.xmlstore.XMLStoreException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MetadataProviderImpl implements IMetadataProvider {
private static class Key {
public String id;
public String lang;
public Key(String id, String lang) {
this.id = id;
if (lang == null || lang.length() == 0) {
this.lang = "";
} else {
this.lang = (new Locale(lang)).getLanguage();
}
}
@Override
public int hashCode() {
return toString().hashCode();
}
@Override
public boolean equals(Object o) {
return toString().equals(o.toString());
}
@Override
public String toString() {
return id + lang;
}
}
private HashMap<Key, ArrayList<IMetadata>> metadataList = new HashMap<Key, ArrayList<IMetadata>>();
private ArrayList<IMetadata> metadata;
private ArrayList<IXMLInfo> entries;
private Locale locale = null;
public MetadataProviderImpl(ArrayList<IXMLInfo> entries) {
this.entries = entries;
}
public void reload() {
metadataList.clear();
readFile();
}
private Stack<String> langStack = new Stack<String>();
private class BaseHandler extends DefaultHandler {
private BaseHandler back;
private IXMLInfo entry;
public BaseHandler(BaseHandler back, IXMLInfo entry) {
this.back = back;
this.entry = entry;
}
public BaseHandler(BaseHandler back) {
this.back = back;
this.entry = back.getEntry();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (attributes.getValue("xml:lang") != null) {
langStack.push(attributes.getValue("xml:lang"));
} else {
langStack.push(langStack.peek() + "");
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
langStack.pop();
getEntry().setContentHandler(back);
}
public IXMLInfo getEntry() {
return entry;
}
}
private class AllHandler extends BaseHandler {
private boolean altFlag;
public AllHandler(IXMLInfo entry) {
super(null, entry);
langStack.clear();
langStack.push("");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if (altFlag) {
if ("item".equals(localName)) {
String importance = attributes.getValue("importance");
if (importance == null || importance.length() == 0) {
importance = "middle";
}
getEntry().setContentHandler(
new ItemHandler(this, importance));
}
} else {
if ("alternative".equals(localName)) {
String type = attributes.getValue("type");
if (type != null && type.equals("audio-description")) {
altFlag = true;
}
}
if ("volumeLevel".equals(localName)) {
// do nothing
}
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("alternative".equals(localName)) {
altFlag = false;
}
// super.endElement(uri, localName, qName);
}
}
private class ItemHandler extends BaseHandler {
private boolean descFlag = false;
private boolean startFlag = false;
private boolean durationFlag = false;
private boolean additionFlag = false;
private boolean waveFlag = false;
private StringBuffer buf = new StringBuffer();
private String start;
private String duration;
private ArrayList<String> speed = new ArrayList<String>();
private ArrayList<String> gender = new ArrayList<String>();
private ArrayList<String> desc = new ArrayList<String>();
private ArrayList<String> lang = new ArrayList<String>();
private ArrayList<String> extended = new ArrayList<String>();
/*
* experimental private ArrayList<String> additions = new
* ArrayList<String>();
*
* private ArrayList<String> additionsLang = new ArrayList<String>();
*
* private ArrayList<String> additionsSpeed = new ArrayList<String>();
*
* private ArrayList<String> additionsGender = new ArrayList<String>();
*/
private ArrayList<String> waveLocal = new ArrayList<String>();
private String importance;
public ItemHandler(BaseHandler back, String importance) {
super(back);
this.importance = importance;
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if ("start".equals(localName)) {
if (attributes.getValue("type").equals("relTime")) {
startFlag = true;
}
} else if ("duration".equals(localName)) {
durationFlag = true;
} else if ("description".equals(localName)) {
descFlag = true;
speed.add(attributes.getValue("speed"));
gender.add(attributes.getValue("gender"));
extended.add(attributes.getValue("extended"));
/*
* } else if ("addition".equals(localName)) { additionFlag =
* true; additionsSpeed.add(attributes.getValue("speed"));
* additionsGender.add(attributes.getValue("gender"));
*/
} else if ("wave".equals(localName)) {
waveFlag = true;
waveLocal.add(attributes.getValue("local"));
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (startFlag) {
buf.append(ch, start, length);
} else if (durationFlag) {
buf.append(ch, start, length);
} else if (descFlag) {
buf.append(ch, start, length);
} else if (additionFlag) {
buf.append(ch, start, length);
} else if (waveFlag) {
buf.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("start".equals(localName)) {
startFlag = false;
start = buf.toString();
buf.delete(0, buf.length());
} else if ("duration".equals(localName)) {
durationFlag = false;
duration = buf.toString();
buf.delete(0, buf.length());
} else if ("description".equals(localName)) {
descFlag = false;
desc.add(buf.toString());
lang.add(langStack.peek());
buf.delete(0, buf.length());
/*
* } else if ("addition".equals(localName)) { additionFlag =
* false; additions.add(buf.toString());
* additionsLang.add(langStack.peek()); buf.delete(0,
* buf.length());
*/
} else if ("wave".equals(localName)) {
waveFlag = false;
// waveLang.add(langStack.peek()); //TODO
buf.delete(0, buf.length());
} else if ("item".equals(localName)) {
for (int i = 0; i < desc.size(); i++) {
MetadataImpl mi = new MetadataImpl(start, duration, desc
.get(i), lang.get(i), importance, speed.get(i),
gender.get(i), extended.get(i));
/*
* for (int j = 0; j < additions.size(); j++) { if
* (additionsLang.get(j).equals(lang.get(i))) {
* mi.setAddition(additions.get(j));
* mi.setAdditionGender(additionsGender.get(j));
* mi.setAdditionSpeed(additionsSpeed.get(j)); } }
*/
for (int j = 0; j < waveLocal.size(); j++) {
// TODO lang
mi.setWavLocal(waveLocal.get(j));
}
// System.out.println(start + ", " + duration + ", " +
// desc.get(i) + ", " + lang.get(i));
Key key = new Key(getEntry().getDocumentation(), lang
.get(i));
ArrayList<IMetadata> list = metadataList.get(key);
if (list == null) {
list = new ArrayList<IMetadata>();
metadataList.put(key, list);
}
list.add(mi);
}
super.endElement(uri, localName, qName);
}
}
}
private void readFile() {
for (int i = 0; i < entries.size(); i++) {
IXMLInfo entry = entries.get(i);
AllHandler ah = new AllHandler(entry);
entry.setContentHandler(ah);
try {
entry.startSAX();
} catch (XMLStoreException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
}
public void setLocale(Locale locale) {
this.locale = locale;
}
ArrayList<ArrayList<IMetadata>> alternatives;
public void prepareMetadata() {
prepareMetadata(this.locale);
}
public void prepareMetadata(Locale locale) {
Set<Key> keys = metadataList.keySet();
alternatives = new ArrayList<ArrayList<IMetadata>>();
for (Iterator<Key> i = keys.iterator(); i.hasNext();) {
Key key = i.next();
if (key.lang.equals(locale.getLanguage())) {
alternatives.add(metadataList.get(key));
}
}
if (alternatives.size() > 0)
setMetadata(alternatives.get(0));
}
public void setMetadata(ArrayList<IMetadata> metadata) {
this.metadata = metadata;
}
public IMetadata getItem(int index) {
if (0 <= index && index < metadata.size())
return metadata.get(index);
return null;
}
public ArrayList<IMetadata> getAllItems() {
return metadata;
}
public int getIndex(int position) {
if (metadata == null)
return 0;
int ret = 0;
for (int i = 0; i < metadata.size(); i++) {
if (metadata.get(i).getStartTime() >= position) {
ret = i - 1;
return ret;
}
}
return metadata.size() - 1;
}
public int getSize() {
if (metadata == null)
return 0;
return metadata.size();
}
public boolean hasMetadata() {
if (metadata == null)
return false;
return metadata.size() > 0;
}
}