/* -*- c-basic-offset: 2; indent-tabs-mode: nil; -*- */
/*
* FreeDots -- MusicXML to braille music transcription
*
* Copyright 2008-2010 Mario Lang All Rights Reserved.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details (a copy is included in the LICENSE.txt file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License
* along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This file is maintained by Mario Lang <mlang@delysid.org>.
*/
package freedots.musicxml;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import freedots.math.Fraction;
import freedots.music.Event;
public final class Direction extends AbstractDirection {
private final List<Element> directionTypes = new ArrayList<Element>();
private Sound sound;
Direction(final Element element,
final int durationMultiplier, final int divisions,
final Fraction offset) {
super(element, durationMultiplier, divisions, offset);
for (Node node = element.getFirstChild(); node != null;
node = node.getNextSibling()) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element child = (Element)node;
if ("direction-type".equals(child.getTagName())) {
directionTypes.add(child);
} else if ("sound".equals(child.getTagName())) {
sound = new Sound(child, getMoment());
}
}
}
}
public boolean isDirective() {
return Score.YES.equalsIgnoreCase(element.getAttribute("directive"));
}
public String getWords() {
// There can be several words elements in several direction-type elements
// TODO: Do we want to add a space when concatenating?
StringBuilder sb = new StringBuilder();
for (Element directionType: directionTypes) {
for (Node node = directionType.getFirstChild(); node != null;
node = node.getNextSibling()) {
if (node.getNodeType() == Node.ELEMENT_NODE
&& "words".equals(node.getNodeName())) {
Element words = (Element)node;
sb.append(words.getTextContent());
}
}
}
if (sb.length() == 0) return null;
return sb.toString();
}
private boolean isPedalType(String type) {
for (Element directionType: directionTypes) {
for (Node node = directionType.getFirstChild(); node != null;
node = node.getNextSibling()) {
if (node.getNodeType() == Node.ELEMENT_NODE
&& "pedal".equals(node.getNodeName())) {
Element pedal = (Element)node;
if (type.equals(pedal.getAttribute("type"))) return true;
}
}
}
return false;
}
public boolean isPedalPress() {
return isPedalType("start");
}
public boolean isPedalRelease() {
return isPedalType("stop");
}
/** Checks if this direction contains dynamics.
* @return a list of found dynamics indicators, or null if no dynamics
* element was found in this direction.
*/
public List<String> getDynamics() {
List<String> dynamics = null;
for (Element directionType: directionTypes) {
for (Node node = directionType.getFirstChild(); node != null;
node = node.getNextSibling()) {
if (node.getNodeType() == Node.ELEMENT_NODE
&& "dynamics".equals(node.getNodeName())) {
if (dynamics == null) dynamics = new ArrayList<String>();
for (Node dynamicsNode = node.getFirstChild(); dynamicsNode != null;
dynamicsNode = dynamicsNode.getNextSibling()) {
if (dynamicsNode.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element)dynamicsNode;
String text;
if ("other-dynamics".equals(element.getTagName())) {
text = element.getTextContent();
} else {
text = element.getTagName();
}
dynamics.add(text);
}
}
}
}
}
return dynamics;
}
public Sound getSound() { return sound; }
// TODO: Incomplete, needs to be rethought
public boolean equalsIgnoreOffset(Event object) {
if (object instanceof Direction) {
Direction other = (Direction)object;
Sound thisSound = this.getSound();
Sound otherSound = other.getSound();
if (thisSound == null || otherSound == null)
return thisSound == otherSound;
return thisSound.equalsIgnoreOffset(otherSound);
}
return false;
}
}