From 7441c191a77bce8f3f77ed4d027ecfa820fd1fe2 Mon Sep 17 00:00:00 2001 From: Jake McGinty Date: Sat, 28 Jun 2014 14:06:15 -0700 Subject: [PATCH] Format outgoing MMS using SMIL. // FREEBIE Closes #1879 --- build.gradle | 5 + .../thoughtcrime/securesms/dom/AttrImpl.java | 108 ++++++ .../securesms/dom/DocumentImpl.java | 194 ++++++++++ .../securesms/dom/ElementImpl.java | 172 +++++++++ .../securesms/dom/NamedNodeMapImpl.java | 87 +++++ .../thoughtcrime/securesms/dom/NodeImpl.java | 273 ++++++++++++++ .../securesms/dom/NodeListImpl.java | 128 +++++++ .../securesms/dom/events/EventImpl.java | 127 +++++++ .../securesms/dom/events/EventTargetImpl.java | 131 +++++++ .../ElementParallelTimeContainerImpl.java | 155 ++++++++ .../ElementSequentialTimeContainerImpl.java | 73 ++++ .../dom/smil/ElementTimeContainerImpl.java | 33 ++ .../securesms/dom/smil/ElementTimeImpl.java | 348 ++++++++++++++++++ .../securesms/dom/smil/SmilDocumentImpl.java | 291 +++++++++++++++ .../securesms/dom/smil/SmilElementImpl.java | 47 +++ .../dom/smil/SmilLayoutElementImpl.java | 63 ++++ .../dom/smil/SmilMediaElementImpl.java | 343 +++++++++++++++++ .../dom/smil/SmilParElementImpl.java | 217 +++++++++++ .../dom/smil/SmilRefElementImpl.java | 29 ++ .../dom/smil/SmilRegionElementImpl.java | 283 ++++++++++++++ .../dom/smil/SmilRegionMediaElementImpl.java | 53 +++ .../dom/smil/SmilRootLayoutElementImpl.java | 84 +++++ .../securesms/dom/smil/TimeImpl.java | 295 +++++++++++++++ .../securesms/dom/smil/TimeListImpl.java | 53 +++ .../dom/smil/parser/SmilXmlSerializer.java | 80 ++++ .../securesms/mms/AudioSlide.java | 21 +- .../securesms/mms/ImageSlide.java | 27 +- src/org/thoughtcrime/securesms/mms/Slide.java | 51 +-- .../thoughtcrime/securesms/mms/SlideDeck.java | 20 +- .../thoughtcrime/securesms/mms/TextSlide.java | 23 +- .../securesms/mms/VideoSlide.java | 30 +- .../thoughtcrime/securesms/util/SmilUtil.java | 75 ++++ 32 files changed, 3878 insertions(+), 41 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/dom/AttrImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/DocumentImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/ElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/NamedNodeMapImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/NodeImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/NodeListImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/events/EventImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/events/EventTargetImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/ElementParallelTimeContainerImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/ElementSequentialTimeContainerImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/ElementTimeContainerImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/ElementTimeImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilDocumentImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilLayoutElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilMediaElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilParElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilRefElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilRegionElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilRegionMediaElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/SmilRootLayoutElementImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/TimeImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/TimeListImpl.java create mode 100644 src/org/thoughtcrime/securesms/dom/smil/parser/SmilXmlSerializer.java create mode 100644 src/org/thoughtcrime/securesms/util/SmilUtil.java diff --git a/build.gradle b/build.gradle index 2bf8a8a953..0ec29add45 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,9 @@ repositories { maven { url "https://raw.github.com/whispersystems/maven/master/gson/releases/" } + maven { + url "https://raw.github.com/whispersystems/maven/master/smil/releases/" + } } dependencies { @@ -27,6 +30,7 @@ dependencies { compile 'se.emilsjolander:stickylistheaders:2.2.0' compile 'com.google.android.gms:play-services:5.0.89' compile 'com.astuetz:pagerslidingtabstrip:1.0.1' + compile 'org.w3c:smil:1.0.0' androidTestCompile 'com.squareup:fest-android:1.0.8' @@ -40,6 +44,7 @@ dependencyVerification { 'se.emilsjolander:stickylistheaders:89146b46c96fea0e40200474a2625cda10fe94891e4128f53cdb42375091b9b6', 'com.google.android.gms:play-services:38f326e525830f1d70f60f594ceafcbdf5b312287ddbecd338fd1ed7958a4b1e', 'com.astuetz:pagerslidingtabstrip:f1641396732c7132a7abb837e482e5ee2b0ebb8d10813fc52bbaec2c15c184c2', + 'org.w3c:smil:085dc40f2bb249651578bfa07499fd08b16ad0886dbe2c4078586a408da62f9b', 'com.google.protobuf:protobuf-java:ad9769a22989e688a46af4d3accc348cc501ced22118033230542bc916e33f0b', 'com.madgag:sc-light-jdk15on:931f39d351429fb96c2f749e7ecb1a256a8ebbf5edca7995c9cc085b94d1841d', 'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab', diff --git a/src/org/thoughtcrime/securesms/dom/AttrImpl.java b/src/org/thoughtcrime/securesms/dom/AttrImpl.java new file mode 100644 index 0000000000..e13e9e25bf --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/AttrImpl.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom; + +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.TypeInfo; + +public class AttrImpl extends NodeImpl implements Attr { + private String mName; + private String mValue; + + /* + * Internal methods + */ + + protected AttrImpl(DocumentImpl owner, String name) { + super(owner); + mName = name; + } + + /* + * Attr Interface Methods + */ + + public String getName() { + return mName; + } + + public Element getOwnerElement() { + // TODO Auto-generated method stub + return null; + } + + public boolean getSpecified() { + return mValue != null; + } + + public String getValue() { + return mValue; + } + + // Instead of setting a Text> with the content of the + // String value as defined in the specs, we directly set here the + // internal mValue member. + public void setValue(String value) throws DOMException { + mValue = value; + } + + /* + * Node Interface Methods + */ + + @Override + public String getNodeName() { + return mName; + } + + @Override + public short getNodeType() { + return Node.ATTRIBUTE_NODE; + } + + @Override + public Node getParentNode() { + return null; + } + + @Override + public Node getPreviousSibling() { + return null; + } + + @Override + public Node getNextSibling() { + return null; + } + + @Override + public void setNodeValue(String nodeValue) throws DOMException { + setValue(nodeValue); + } + + public TypeInfo getSchemaTypeInfo() { + return null; + } + + public boolean isId() { + return false; + } +} diff --git a/src/org/thoughtcrime/securesms/dom/DocumentImpl.java b/src/org/thoughtcrime/securesms/dom/DocumentImpl.java new file mode 100644 index 0000000000..08816627a7 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/DocumentImpl.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom; + +import org.w3c.dom.Attr; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; +import org.w3c.dom.DOMConfiguration; +import org.w3c.dom.DOMException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.DocumentType; +import org.w3c.dom.Element; +import org.w3c.dom.EntityReference; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; + +public abstract class DocumentImpl extends NodeImpl implements Document { + + /* + * Internal methods + */ + + public DocumentImpl() { + super(null); + } + + /* + * Document Interface Methods + */ + + public Attr createAttribute(String name) throws DOMException { + return new AttrImpl(this, name); + } + + public Attr createAttributeNS(String namespaceURI, String qualifiedName) + throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public CDATASection createCDATASection(String data) throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public Comment createComment(String data) { + // TODO Auto-generated method stub + return null; + } + + public DocumentFragment createDocumentFragment() { + // TODO Auto-generated method stub + return null; + } + + public abstract Element createElement(String tagName) throws DOMException; + + public Element createElementNS(String namespaceURI, String qualifiedName) + throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public EntityReference createEntityReference(String name) throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public ProcessingInstruction createProcessingInstruction(String target, String data) + throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public Text createTextNode(String data) { + // TODO Auto-generated method stub + return null; + } + + public DocumentType getDoctype() { + // TODO Auto-generated method stub + return null; + } + + public abstract Element getDocumentElement(); + + public Element getElementById(String elementId) { + // TODO Auto-generated method stub + return null; + } + + public NodeList getElementsByTagName(String tagname) { + // TODO Auto-generated method stub + return null; + } + + public NodeList getElementsByTagNameNS(String namespaceURI, String localName) { + // TODO Auto-generated method stub + return null; + } + + public DOMImplementation getImplementation() { + // TODO Auto-generated method stub + return null; + } + + public Node importNode(Node importedNode, boolean deep) throws DOMException { + // TODO Auto-generated method stub + return null; + } + + /* + * Node Interface methods + */ + + @Override + public short getNodeType() { + return Node.DOCUMENT_NODE; + } + + @Override + public String getNodeName() { + // The value of nodeName is "#document" when Node is a Document + return "#document"; + } + + public String getInputEncoding() { + return null; + } + + public String getXmlEncoding() { + return null; + } + + public boolean getXmlStandalone() { + return false; + } + + public void setXmlStandalone(boolean xmlStandalone) throws DOMException {} + + public String getXmlVersion() { + return null; + } + + public void setXmlVersion(String xmlVersion) throws DOMException {} + + public boolean getStrictErrorChecking() { + return true; + } + + public void setStrictErrorChecking(boolean strictErrorChecking) {} + + public String getDocumentURI() { + return null; + } + + public void setDocumentURI(String documentURI) {} + + public Node adoptNode(Node source) throws DOMException { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public DOMConfiguration getDomConfig() { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public void normalizeDocument() { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public Node renameNode(Node n, String namespaceURI, String qualifiedName) + throws DOMException { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } +} diff --git a/src/org/thoughtcrime/securesms/dom/ElementImpl.java b/src/org/thoughtcrime/securesms/dom/ElementImpl.java new file mode 100644 index 0000000000..583858f4ee --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/ElementImpl.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom; + +import org.w3c.dom.Attr; +import org.w3c.dom.DOMException; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.NodeList; +import org.w3c.dom.TypeInfo; + +public class ElementImpl extends NodeImpl implements Element { + private String mTagName; + private NamedNodeMap mAttributes = new NamedNodeMapImpl(); + + /* + * Internal methods + */ + + protected ElementImpl(DocumentImpl owner, String tagName) { + super(owner); + mTagName = tagName; + } + + /* + * Element Interface methods + */ + + public String getAttribute(String name) { + Attr attrNode = getAttributeNode(name); + String attrValue = ""; + if (attrNode != null) { + attrValue = attrNode.getValue(); + } + return attrValue; + } + + public String getAttributeNS(String namespaceURI, String localName) { + // TODO Auto-generated method stub + return null; + } + + public Attr getAttributeNode(String name) { + return (Attr)mAttributes.getNamedItem(name); + } + + public Attr getAttributeNodeNS(String namespaceURI, String localName) { + // TODO Auto-generated method stub + return null; + } + + public NodeList getElementsByTagName(String name) { + return new NodeListImpl(this, name, true); + } + + public NodeList getElementsByTagNameNS(String namespaceURI, String localName) { + // TODO Auto-generated method stub + return null; + } + + public String getTagName() { + return mTagName; + } + + public boolean hasAttribute(String name) { + return (getAttributeNode(name) != null); + } + + public boolean hasAttributeNS(String namespaceURI, String localName) { + // TODO Auto-generated method stub + return false; + } + + public void removeAttribute(String name) throws DOMException { + // TODO Auto-generated method stub + + } + + public void removeAttributeNS(String namespaceURI, String localName) + throws DOMException { + // TODO Auto-generated method stub + + } + + public Attr removeAttributeNode(Attr oldAttr) throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public void setAttribute(String name, String value) throws DOMException { + Attr attribute = getAttributeNode(name); + if (attribute == null) { + attribute = mOwnerDocument.createAttribute(name); + } + attribute.setNodeValue(value); + mAttributes.setNamedItem(attribute); + } + + public void setAttributeNS(String namespaceURI, String qualifiedName, + String value) throws DOMException { + // TODO Auto-generated method stub + + } + + public Attr setAttributeNode(Attr newAttr) throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public Attr setAttributeNodeNS(Attr newAttr) throws DOMException { + // TODO Auto-generated method stub + return null; + } + + /* + * Node Interface methods + */ + + @Override + public short getNodeType() { + return ELEMENT_NODE; + } + + @Override + public String getNodeName() { + // The value of nodeName is tagName when Node is an Element + return mTagName; + } + + @Override + public NamedNodeMap getAttributes() { + return mAttributes; + } + + @Override + public boolean hasAttributes() { + return (mAttributes.getLength() > 0); + } + + public TypeInfo getSchemaTypeInfo() { + return null; + } + + public void setIdAttribute(String name, boolean isId) throws DOMException { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public void setIdAttributeNS(String namespaceURI, String localName, + boolean isId) throws DOMException { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public void setIdAttributeNode(Attr idAttr, boolean isId) + throws DOMException { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } +} diff --git a/src/org/thoughtcrime/securesms/dom/NamedNodeMapImpl.java b/src/org/thoughtcrime/securesms/dom/NamedNodeMapImpl.java new file mode 100644 index 0000000000..9eff2dfe74 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/NamedNodeMapImpl.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom; + +import java.util.Vector; + +import org.w3c.dom.DOMException; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; + +public class NamedNodeMapImpl implements NamedNodeMap { + + private Vector mNodes = new Vector(); + + public int getLength() { + return mNodes.size(); + } + + public Node getNamedItem(String name) { + Node node = null; + for (int i = 0; i < mNodes.size(); i++) { + if (name.equals(mNodes.elementAt(i).getNodeName())) { + node = mNodes.elementAt(i); + break; + } + } + return node; + } + + public Node getNamedItemNS(String namespaceURI, String localName) { + // TODO Auto-generated method stub + return null; + } + + public Node item(int index) { + if (index < mNodes.size()) { + return mNodes.elementAt(index); + } + return null; + } + + public Node removeNamedItem(String name) throws DOMException { + Node node = getNamedItem(name); + if (node == null) { + throw new DOMException(DOMException.NOT_FOUND_ERR, "Not found"); + } else { + mNodes.remove(node); + } + return node; + } + + public Node removeNamedItemNS(String namespaceURI, String localName) + throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public Node setNamedItem(Node arg) throws DOMException { + Node existing = getNamedItem(arg.getNodeName()); + if (existing != null) { + mNodes.remove(existing); + } + mNodes.add(arg); + return existing; + } + + public Node setNamedItemNS(Node arg) throws DOMException { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/org/thoughtcrime/securesms/dom/NodeImpl.java b/src/org/thoughtcrime/securesms/dom/NodeImpl.java new file mode 100644 index 0000000000..1b38e63105 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/NodeImpl.java @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom; + +import java.util.NoSuchElementException; +import java.util.Vector; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.UserDataHandler; +import org.w3c.dom.events.Event; +import org.w3c.dom.events.EventException; +import org.w3c.dom.events.EventListener; +import org.w3c.dom.events.EventTarget; + +import org.thoughtcrime.securesms.dom.events.EventTargetImpl; + +public abstract class NodeImpl implements Node, EventTarget { + private Node mParentNode; + private final Vector mChildNodes = new Vector(); + DocumentImpl mOwnerDocument; + private final EventTarget mEventTarget = new EventTargetImpl(this); + + /* + * Internal methods + */ + + protected NodeImpl(DocumentImpl owner) { + mOwnerDocument = owner; + } + + /* + * Node Interface Methods + */ + + public Node appendChild(Node newChild) throws DOMException { + ((NodeImpl)newChild).setParentNode(this); + mChildNodes.remove(newChild); + mChildNodes.add(newChild); + return newChild; + } + + public Node cloneNode(boolean deep) { + // TODO Auto-generated method stub + return null; + } + + public NamedNodeMap getAttributes() { + // Default. Override in Element. + return null; + } + + public NodeList getChildNodes() { + return new NodeListImpl(this, null, false); + } + + public Node getFirstChild() { + Node firstChild = null; + try { + firstChild = mChildNodes.firstElement(); + } + catch (NoSuchElementException e) { + // Ignore and return null + } + return firstChild; + } + + public Node getLastChild() { + Node lastChild = null; + try { + lastChild = mChildNodes.lastElement(); + } + catch (NoSuchElementException e) { + // Ignore and return null + } + return lastChild; + } + + public String getLocalName() { + // TODO Auto-generated method stub + return null; + } + + public String getNamespaceURI() { + // TODO Auto-generated method stub + return null; + } + + public Node getNextSibling() { + if ((mParentNode != null) && (this != mParentNode.getLastChild())) { + Vector siblings = ((NodeImpl)mParentNode).mChildNodes; + int indexOfThis = siblings.indexOf(this); + return siblings.elementAt(indexOfThis + 1); + } + return null; + } + + public abstract String getNodeName(); + + public abstract short getNodeType(); + + public String getNodeValue() throws DOMException { + // Default behaviour. Override if required. + return null; + } + + public Document getOwnerDocument() { + return mOwnerDocument; + } + + public Node getParentNode() { + return mParentNode; + } + + public String getPrefix() { + // TODO Auto-generated method stub + return null; + } + + public Node getPreviousSibling() { + if ((mParentNode != null) && (this != mParentNode.getFirstChild())) { + Vector siblings = ((NodeImpl)mParentNode).mChildNodes; + int indexOfThis = siblings.indexOf(this); + return siblings.elementAt(indexOfThis - 1); + } + return null; + } + + public boolean hasAttributes() { + // Default. Override in Element. + return false; + } + + public boolean hasChildNodes() { + return !(mChildNodes.isEmpty()); + } + + public Node insertBefore(Node newChild, Node refChild) throws DOMException { + // TODO Auto-generated method stub + return null; + } + + public boolean isSupported(String feature, String version) { + // TODO Auto-generated method stub + return false; + } + + public void normalize() { + // TODO Auto-generated method stub + } + + public Node removeChild(Node oldChild) throws DOMException { + if (mChildNodes.contains(oldChild)) { + mChildNodes.remove(oldChild); + ((NodeImpl)oldChild).setParentNode(null); + } else { + throw new DOMException(DOMException.NOT_FOUND_ERR, "Child does not exist"); + } + return null; + } + + public Node replaceChild(Node newChild, Node oldChild) throws DOMException { + if (mChildNodes.contains(oldChild)) { + // Try to remove the new child if available + try { + mChildNodes.remove(newChild); + } catch (DOMException e) { + // Ignore exception + } + mChildNodes.setElementAt(newChild, mChildNodes.indexOf(oldChild)); + ((NodeImpl)newChild).setParentNode(this); + ((NodeImpl)oldChild).setParentNode(null); + } else { + throw new DOMException(DOMException.NOT_FOUND_ERR, "Old child does not exist"); + } + return oldChild; + } + + public void setNodeValue(String nodeValue) throws DOMException { + // Default behaviour. Override if required. + } + + public void setPrefix(String prefix) throws DOMException { + // TODO Auto-generated method stub + } + + private void setParentNode(Node parentNode) { + mParentNode = parentNode; + } + + /* + * EventTarget Interface + */ + + public void addEventListener(String type, EventListener listener, boolean useCapture) { + mEventTarget.addEventListener(type, listener, useCapture); + } + + public void removeEventListener(String type, EventListener listener, boolean useCapture) { + mEventTarget.removeEventListener(type, listener, useCapture); + } + + public boolean dispatchEvent(Event evt) throws EventException { + return mEventTarget.dispatchEvent(evt); + } + + public String getBaseURI() { + return null; + } + + public short compareDocumentPosition(Node other) throws DOMException { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public String getTextContent() throws DOMException { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public void setTextContent(String textContent) throws DOMException { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public boolean isSameNode(Node other) { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public String lookupPrefix(String namespaceURI) { + return null; + } + + public boolean isDefaultNamespace(String namespaceURI) { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public String lookupNamespaceURI(String prefix) { + return null; + } + + public boolean isEqualNode(Node arg) { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public Object getFeature(String feature, String version) { + return null; + } + + public Object setUserData(String key, Object data, + UserDataHandler handler) { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, null); + } + + public Object getUserData(String key) { + return null; + } +} diff --git a/src/org/thoughtcrime/securesms/dom/NodeListImpl.java b/src/org/thoughtcrime/securesms/dom/NodeListImpl.java new file mode 100644 index 0000000000..9ac9161587 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/NodeListImpl.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom; + +import java.util.ArrayList; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class NodeListImpl implements NodeList { + private ArrayList mSearchNodes; + private ArrayList mStaticNodes; + private Node mRootNode; + private String mTagName; + private boolean mDeepSearch; + + /* + * Internal Interface + */ + + /** + * Constructs a NodeList by searching for all descendants or the direct + * children of a root node with a given tag name. + * @param rootNode The root Node of the search. + * @param tagName The tag name to be searched for. If null, all descendants + * will be returned. + * @param deep Limit the search to the direct children of rootNode if false, + * to all descendants otherwise. + */ + public NodeListImpl(Node rootNode, String tagName, boolean deepSearch) { + mRootNode = rootNode; + mTagName = tagName; + mDeepSearch = deepSearch; + } + + /** + * Constructs a NodeList for a given static node list. + * @param nodes The static node list. + */ + public NodeListImpl(ArrayList nodes) { + mStaticNodes = nodes; + } + + /* + * NodeListImpl Interface + */ + + public int getLength() { + if (mStaticNodes == null) { + fillList(mRootNode); + return mSearchNodes.size(); + } else { + return mStaticNodes.size(); + } + } + + public Node item(int index) { + Node node = null; + if (mStaticNodes == null) { + fillList(mRootNode); + try { + node = mSearchNodes.get(index); + } catch (IndexOutOfBoundsException e) { + // Do nothing and return null + } + } else { + try { + node = mStaticNodes.get(index); + } catch (IndexOutOfBoundsException e) { + // Do nothing and return null + } + } + return node; + } + + /** + * A preorder traversal is done in the following order: + *
    + *
  • Visit root. + *
  • Traverse children from left to right in preorder. + *
+ * This method fills the live node list. + * @param The root of preorder traversal + * @return The next match + */ + private void fillList(Node node) { + // (Re)-initialize the container if this is the start of the search. + // Visit the root of this iteration otherwise. + if (node == mRootNode) { + mSearchNodes = new ArrayList(); + } else { + if ((mTagName == null) || node.getNodeName().equals(mTagName)) { + mSearchNodes.add(node); + } + } + + // Descend one generation... + node = node.getFirstChild(); + + // ...and visit in preorder the children if we are in deep search + // or directly add the children to the list otherwise. + while (node != null) { + if (mDeepSearch) { + fillList(node); + } else { + if ((mTagName == null) || node.getNodeName().equals(mTagName)) { + mSearchNodes.add(node); + } + } + node = node.getNextSibling(); + } + } +} diff --git a/src/org/thoughtcrime/securesms/dom/events/EventImpl.java b/src/org/thoughtcrime/securesms/dom/events/EventImpl.java new file mode 100644 index 0000000000..24c3ef6282 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/events/EventImpl.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom.events; + +import org.w3c.dom.events.Event; +import org.w3c.dom.events.EventTarget; + +public class EventImpl implements Event { + + // Event type informations + private String mEventType; + private boolean mCanBubble; + private boolean mCancelable; + + // Flags whether the event type information was set + // FIXME: Can we use mEventType for this purpose? + private boolean mInitialized; + + // Target of this event + private EventTarget mTarget; + + // Event status variables + private short mEventPhase; + private boolean mStopPropagation; + private boolean mPreventDefault; + private EventTarget mCurrentTarget; + private int mSeekTo; + + private final long mTimeStamp = System.currentTimeMillis(); + + public boolean getBubbles() { + return mCanBubble; + } + + public boolean getCancelable() { + return mCancelable; + } + + public EventTarget getCurrentTarget() { + return mCurrentTarget; + } + + public short getEventPhase() { + return mEventPhase; + } + + public EventTarget getTarget() { + return mTarget; + } + + public long getTimeStamp() { + return mTimeStamp; + } + + public String getType() { + return mEventType; + } + + public void initEvent(String eventTypeArg, boolean canBubbleArg, + boolean cancelableArg) { + mEventType = eventTypeArg; + mCanBubble = canBubbleArg; + mCancelable = cancelableArg; + mInitialized = true; + } + + public void initEvent(String eventTypeArg, boolean canBubbleArg, boolean cancelableArg, + int seekTo) { + mSeekTo = seekTo; + initEvent(eventTypeArg, canBubbleArg, cancelableArg); + } + + public void preventDefault() { + mPreventDefault = true; + } + + public void stopPropagation() { + mStopPropagation = true; + } + + /* + * Internal Interface + */ + + boolean isInitialized() { + return mInitialized; + } + + boolean isPreventDefault() { + return mPreventDefault; + } + + boolean isPropogationStopped() { + return mStopPropagation; + } + + void setTarget(EventTarget target) { + mTarget = target; + } + + void setEventPhase(short eventPhase) { + mEventPhase = eventPhase; + } + + void setCurrentTarget(EventTarget currentTarget) { + mCurrentTarget = currentTarget; + } + + public int getSeekTo() { + return mSeekTo; + } +} diff --git a/src/org/thoughtcrime/securesms/dom/events/EventTargetImpl.java b/src/org/thoughtcrime/securesms/dom/events/EventTargetImpl.java new file mode 100644 index 0000000000..b629b6e9ca --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/events/EventTargetImpl.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom.events; + +import java.util.ArrayList; + +import org.w3c.dom.events.Event; +import org.w3c.dom.events.EventException; +import org.w3c.dom.events.EventListener; +import org.w3c.dom.events.EventTarget; + +import android.util.Log; + +public class EventTargetImpl implements EventTarget { + private static final String TAG = "EventTargetImpl"; + private ArrayList mListenerEntries; + private EventTarget mNodeTarget; + + static class EventListenerEntry + { + final String mType; + final EventListener mListener; + final boolean mUseCapture; + + EventListenerEntry(String type, EventListener listener, boolean useCapture) + { + mType = type; + mListener = listener; + mUseCapture = useCapture; + } + } + + public EventTargetImpl(EventTarget target) { + mNodeTarget = target; + } + + public void addEventListener(String type, EventListener listener, boolean useCapture) { + if ((type == null) || type.equals("") || (listener == null)) { + return; + } + + // Make sure we have only one entry + removeEventListener(type, listener, useCapture); + + if (mListenerEntries == null) { + mListenerEntries = new ArrayList(); + } + mListenerEntries.add(new EventListenerEntry(type, listener, useCapture)); + } + + public boolean dispatchEvent(Event evt) throws EventException { + // We need to use the internal APIs to modify and access the event status + EventImpl eventImpl = (EventImpl)evt; + + if (!eventImpl.isInitialized()) { + throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR, + "Event not initialized"); + } else if ((eventImpl.getType() == null) || eventImpl.getType().equals("")) { + throw new EventException(EventException.UNSPECIFIED_EVENT_TYPE_ERR, + "Unspecified even type"); + } + + // Initialize event status + eventImpl.setTarget(mNodeTarget); + + // TODO: At this point, to support event capturing and bubbling, we should + // establish the chain of EventTargets from the top of the tree to this + // event's target. + + // TODO: CAPTURING_PHASE skipped + + // Handle AT_TARGET + // Invoke handleEvent of non-capturing listeners on this EventTarget. + eventImpl.setEventPhase(Event.AT_TARGET); + eventImpl.setCurrentTarget(mNodeTarget); + if (!eventImpl.isPropogationStopped() && (mListenerEntries != null)) { + for (int i = 0; i < mListenerEntries.size(); i++) { + EventListenerEntry listenerEntry = mListenerEntries.get(i); + if (!listenerEntry.mUseCapture + && listenerEntry.mType.equals(eventImpl.getType())) { + try { + listenerEntry.mListener.handleEvent(eventImpl); + } + catch (Exception e) { + // Any exceptions thrown inside an EventListener will + // not stop propagation of the event + Log.w(TAG, "Catched EventListener exception", e); + } + } + } + } + + if (eventImpl.getBubbles()) { + // TODO: BUBBLING_PHASE skipped + } + + return eventImpl.isPreventDefault(); + } + + public void removeEventListener(String type, EventListener listener, + boolean useCapture) { + if (null == mListenerEntries) { + return; + } + for (int i = 0; i < mListenerEntries.size(); i ++) { + EventListenerEntry listenerEntry = mListenerEntries.get(i); + if ((listenerEntry.mUseCapture == useCapture) + && (listenerEntry.mListener == listener) + && listenerEntry.mType.equals(type)) { + mListenerEntries.remove(i); + break; + } + } + } + +} diff --git a/src/org/thoughtcrime/securesms/dom/smil/ElementParallelTimeContainerImpl.java b/src/org/thoughtcrime/securesms/dom/smil/ElementParallelTimeContainerImpl.java new file mode 100644 index 0000000000..7a1d15d965 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/smil/ElementParallelTimeContainerImpl.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom.smil; + +import java.util.ArrayList; + +import org.w3c.dom.DOMException; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.smil.ElementParallelTimeContainer; +import org.w3c.dom.smil.ElementTime; +import org.w3c.dom.smil.SMILElement; +import org.w3c.dom.smil.Time; +import org.w3c.dom.smil.TimeList; + +import org.thoughtcrime.securesms.dom.NodeListImpl; + +public abstract class ElementParallelTimeContainerImpl extends ElementTimeContainerImpl + implements ElementParallelTimeContainer { + private final static String ENDSYNC_ATTRIBUTE_NAME = "endsync"; + private final static String ENDSYNC_FIRST = "first"; + private final static String ENDSYNC_LAST = "last"; + private final static String ENDSYNC_ALL = "all"; + private final static String ENDSYNC_MEDIA = "media"; + + /* + * Internal Interface + */ + + ElementParallelTimeContainerImpl(SMILElement element) { + super(element); + } + + public String getEndSync() { + String endsync = mSmilElement.getAttribute(ENDSYNC_ATTRIBUTE_NAME); + if ((endsync == null) || (endsync.length() == 0)) { + setEndSync(ENDSYNC_LAST); + return ENDSYNC_LAST; + } + if (ENDSYNC_FIRST.equals(endsync) || ENDSYNC_LAST.equals(endsync) || + ENDSYNC_ALL.equals(endsync) || ENDSYNC_MEDIA.equals(endsync)) { + return endsync; + } + + // FIXME add the checking for ID-Value and smil1.0-Id-value. + + setEndSync(ENDSYNC_LAST); + return ENDSYNC_LAST; + } + + public void setEndSync(String endSync) throws DOMException { + if (ENDSYNC_FIRST.equals(endSync) || ENDSYNC_LAST.equals(endSync) || + ENDSYNC_ALL.equals(endSync) || ENDSYNC_MEDIA.equals(endSync)) { + mSmilElement.setAttribute(ENDSYNC_ATTRIBUTE_NAME, endSync); + } else { // FIXME add the support for ID-Value and smil1.0-Id-value. + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, + "Unsupported endsync value" + endSync); + } + } + + @Override + public float getDur() { + float dur = super.getDur(); + if (dur == 0) { + dur = getImplicitDuration(); + } + return dur; + } + + public float getImplicitDuration() { + float dur = -1.0F; + if (ENDSYNC_LAST.equals(getEndSync())) { + NodeList children = getTimeChildren(); + for (int i = 0; i < children.getLength(); ++i) { + ElementTime child = (ElementTime) children.item(i); + TimeList endTimeList = child.getEnd(); + for (int j = 0; j < endTimeList.getLength(); ++j) { + Time endTime = endTimeList.item(j); + if (endTime.getTimeType() == Time.SMIL_TIME_INDEFINITE) { + // Return "indefinite" here. + return -1.0F; + } + if (endTime.getResolved()) { + float end = (float)endTime.getResolvedOffset(); + dur = (end > dur) ? end : dur; + } + } + } + } // Other endsync types are not supported now. + + return dur; + } + + public NodeList getActiveChildrenAt(float instant) { + /* + * Find the closest Time of ElementTime before instant. + * Add ElementTime to list of active elements if the Time belongs to the begin-list, + * do not add it otherwise. + */ + ArrayList activeChildren = new ArrayList(); + NodeList children = getTimeChildren(); + int childrenLen = children.getLength(); + for (int i = 0; i < childrenLen; ++i) { + double maxOffset = 0.0; + boolean active = false; + ElementTime child = (ElementTime) children.item(i); + + TimeList beginList = child.getBegin(); + int len = beginList.getLength(); + for (int j = 0; j < len; ++j) { + Time begin = beginList.item(j); + if (begin.getResolved()) { + double resolvedOffset = begin.getResolvedOffset() * 1000.0; + if ((resolvedOffset <= instant) && (resolvedOffset >= maxOffset)) { + maxOffset = resolvedOffset; + active = true; + } + } + } + + TimeList endList = child.getEnd(); + len = endList.getLength(); + for (int j = 0; j < len; ++j) { + Time end = endList.item(j); + if (end.getResolved()) { + double resolvedOffset = end.getResolvedOffset() * 1000.0; + if ((resolvedOffset <= instant) && (resolvedOffset >= maxOffset)) { + maxOffset = resolvedOffset; + active = false; + } + } + } + + if (active) { + activeChildren.add((Node) child); + } + } + return new NodeListImpl(activeChildren); + } +} diff --git a/src/org/thoughtcrime/securesms/dom/smil/ElementSequentialTimeContainerImpl.java b/src/org/thoughtcrime/securesms/dom/smil/ElementSequentialTimeContainerImpl.java new file mode 100644 index 0000000000..5ef5837a07 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/smil/ElementSequentialTimeContainerImpl.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom.smil; + +import java.util.ArrayList; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.smil.ElementSequentialTimeContainer; +import org.w3c.dom.smil.ElementTime; +import org.w3c.dom.smil.SMILElement; + +import org.thoughtcrime.securesms.dom.NodeListImpl; + +public abstract class ElementSequentialTimeContainerImpl extends + ElementTimeContainerImpl implements ElementSequentialTimeContainer { + + /* + * Internal Interface + */ + + ElementSequentialTimeContainerImpl(SMILElement element) { + super(element); + } + + /* + * ElementSequentialTimeContainer Interface + */ + + public NodeList getActiveChildrenAt(float instant) { + NodeList allChildren = this.getTimeChildren(); + ArrayList nodes = new ArrayList(); + for (int i = 0; i < allChildren.getLength(); i++) { + instant -= ((ElementTime) allChildren.item(i)).getDur(); + if (instant < 0) { + nodes.add(allChildren.item(i)); + return new NodeListImpl(nodes); + } + } + return new NodeListImpl(nodes); + } + + public float getDur() { + float dur = super.getDur(); + if (dur == 0) { + NodeList children = getTimeChildren(); + for (int i = 0; i < children.getLength(); ++i) { + ElementTime child = (ElementTime) children.item(i); + if (child.getDur() < 0) { + // Return "indefinite" since containing a child whose duration is indefinite. + return -1.0F; + } + dur += child.getDur(); + } + } + return dur; + } +} diff --git a/src/org/thoughtcrime/securesms/dom/smil/ElementTimeContainerImpl.java b/src/org/thoughtcrime/securesms/dom/smil/ElementTimeContainerImpl.java new file mode 100644 index 0000000000..63c64b8603 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/smil/ElementTimeContainerImpl.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007 Esmertec AG. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom.smil; + +import org.w3c.dom.smil.ElementTimeContainer; +import org.w3c.dom.smil.SMILElement; + +public abstract class ElementTimeContainerImpl extends ElementTimeImpl implements + ElementTimeContainer { + + /* + * Internal Interface + */ + + ElementTimeContainerImpl(SMILElement element) { + super(element); + } +} diff --git a/src/org/thoughtcrime/securesms/dom/smil/ElementTimeImpl.java b/src/org/thoughtcrime/securesms/dom/smil/ElementTimeImpl.java new file mode 100644 index 0000000000..3c50600056 --- /dev/null +++ b/src/org/thoughtcrime/securesms/dom/smil/ElementTimeImpl.java @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2007-2008 Esmertec AG. + * Copyright (C) 2007-2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thoughtcrime.securesms.dom.smil; + +import java.util.ArrayList; + +import org.w3c.dom.DOMException; +import org.w3c.dom.smil.ElementTime; +import org.w3c.dom.smil.SMILElement; +import org.w3c.dom.smil.Time; +import org.w3c.dom.smil.TimeList; + +import android.util.Log; + +public abstract class ElementTimeImpl implements ElementTime { + private static final String TAG = "ElementTimeImpl"; + + private static final String FILL_REMOVE_ATTRIBUTE = "remove"; + private static final String FILL_FREEZE_ATTRIBUTE = "freeze"; + private static final String FILL_HOLD_ATTRIBUTE = "hold"; + private static final String FILL_TRANSITION_ATTRIBUTE = "transition"; + private static final String FILL_AUTO_ATTRIBUTE = "auto"; + private static final String FILL_ATTRIBUTE_NAME = "fill"; + private static final String FILLDEFAULT_ATTRIBUTE_NAME = "fillDefault"; + + final SMILElement mSmilElement; + + /* + * Internal Interface + */ + ElementTimeImpl(SMILElement element) { + mSmilElement = element; + } + + // Default implementation. Override if required. + int getBeginConstraints() { + return TimeImpl.ALLOW_ALL; + } + + // Default implementation. Override if required + int getEndConstraints() { + return TimeImpl.ALLOW_ALL; + } + + /** + * To get the parent node on the ElementTime tree. It is in opposition to getTimeChildren. + * @return the parent ElementTime. Returns null if there is no parent. + */ + abstract ElementTime getParentElementTime(); + + /* + * ElementTime Interface + */ + + public TimeList getBegin() { + String[] beginTimeStringList = mSmilElement.getAttribute("begin").split(";"); + + // TODO: Check other constraints on parsed values, e.g., "single, non-negative offset values + ArrayList