Project: bml_lib License: BSD Dependencies: Used by: |
bml_lib/src/edu/wpi/hri/bml/behavior/BehaviorList.javaGo to the documentation of this file.00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, Worcester Polytechnic Institute 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Worcester Polytechnic Institute. nor the names 00018 * of its contributors may be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 */ 00034 package edu.wpi.hri.bml.behavior; 00035 00036 import java.io.StringReader; 00037 import java.util.ArrayList; 00038 import java.util.HashMap; 00039 import java.util.Iterator; 00040 import java.util.List; 00041 import java.util.Map; 00042 00043 import org.w3c.dom.Document; 00044 import org.w3c.dom.Element; 00045 import org.w3c.dom.NodeList; 00046 00047 import ros.pkg.bml_msgs.msg.BehaviorResult; 00048 import ros.pkg.bml_msgs.msg.Flag; 00049 import edu.wpi.hri.bml.XMLInterface; 00050 import edu.wpi.hri.bml.behavior.BehaviorEnums.BehaviorType; 00051 import edu.wpi.hri.bml.behavior.SyncRef.SyncPoint; 00052 import edu.wpi.hri.log.Logger; 00053 import edu.wpi.hri.log.Logger.Colors; 00054 import edu.wpi.hri.log.Logger.LoggerLevel; 00055 00062 public class BehaviorList implements Iterable<Behavior> { 00063 00064 private static final String ID_ATTR = "id"; 00065 00066 protected final XMLInterface xml; 00067 protected final Logger listLogger; 00068 private final ConstraintBehavior requiredCons; 00069 private final ConstraintBehavior optionalCons; 00070 private final List<EmitBehavior> emits; 00071 private final List<FaceBehavior> faces; 00072 private final List<GazeBehavior> gazes; 00073 private final List<GestureBehavior> gestures; 00074 private final List<HeadBehavior> heads; 00075 private final List<LipsBehavior> lips; 00076 private final List<LocomotionBehavior> locomotions; 00077 private final List<SpeechBehavior> speeches; 00078 protected final Map<String, Behavior> map; 00079 private final ArrayList<BehaviorResult> results; 00080 private final String id; 00081 00093 public BehaviorList(Logger logger, XMLInterface xml, Element root) { 00094 this(logger, xml, root.getAttribute(ID_ATTR)); 00095 00096 // copy paste is my friend here, for type safety these have to be done 00097 // separately and then stored 00098 00099 // then for each sub element in the root that is good, parse it 00100 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading constraints"); 00101 NodeList list = root 00102 .getElementsByTagName(BehaviorType.CONSTRAINT.elementName); 00103 for (int c = 0; c < list.getLength(); c++) { 00104 // each constraint must be merged into the good constraint 00105 ConstraintBehavior cb = new ConstraintBehavior(logger, 00106 (Element) list.item(c)); 00107 00108 if (cb.isRequired()) { 00109 this.requiredCons.getBefore().addAll(cb.getBefore()); 00110 this.requiredCons.getSynchronize().addAll(cb.getSynchronize()); 00111 this.requiredCons.getAfter().addAll(cb.getAfter()); 00112 } else { 00113 this.optionalCons.getBefore().addAll(cb.getBefore()); 00114 this.optionalCons.getSynchronize().addAll(cb.getSynchronize()); 00115 this.optionalCons.getAfter().addAll(cb.getAfter()); 00116 } 00117 } 00118 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Found " 00119 + this.optionalCons.getBefore().size() + " before, " 00120 + this.optionalCons.getSynchronize().size() + " synchronized, " 00121 + this.optionalCons.getAfter().size() 00122 + " after in optional cons"); 00123 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Found " 00124 + this.requiredCons.getBefore().size() + " before, " 00125 + this.requiredCons.getSynchronize().size() + " synchronized, " 00126 + this.requiredCons.getAfter().size() 00127 + " after in required cons"); 00128 00129 // then for each sub element in the root that is good, parse it 00130 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading emits"); 00131 list = root.getElementsByTagName(BehaviorType.EMIT.elementName); 00132 for (int c = 0; c < list.getLength(); c++) 00133 this.emits.add(new EmitBehavior(logger, (Element) list.item(c))); 00134 00135 // then for each sub element in the root that is good, parse it 00136 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading faces"); 00137 list = root.getElementsByTagName(BehaviorType.FACE.elementName); 00138 for (int c = 0; c < list.getLength(); c++) 00139 this.faces.add(new FaceBehavior(logger, (Element) list.item(c))); 00140 00141 // then for each sub element in the root that is good, parse it 00142 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading gazes"); 00143 list = root.getElementsByTagName(BehaviorType.GAZE.elementName); 00144 for (int c = 0; c < list.getLength(); c++) 00145 this.gazes.add(new GazeBehavior(logger, (Element) list.item(c))); 00146 00147 // then for each sub element in the root that is good, parse it 00148 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading gestures"); 00149 list = root.getElementsByTagName(BehaviorType.GESTURE.elementName); 00150 for (int c = 0; c < list.getLength(); c++) 00151 this.gestures.add(new GestureBehavior(logger, (Element) list 00152 .item(c))); 00153 00154 // then for each sub element in the root that is good, parse it 00155 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading heads"); 00156 list = root.getElementsByTagName(BehaviorType.HEAD.elementName); 00157 for (int c = 0; c < list.getLength(); c++) 00158 this.heads.add(new HeadBehavior(logger, (Element) list.item(c))); 00159 00160 // then for each sub element in the root that is good, parse it 00161 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading lips"); 00162 list = root.getElementsByTagName(BehaviorType.LIPS.elementName); 00163 for (int c = 0; c < list.getLength(); c++) 00164 this.lips.add(new LipsBehavior(logger, (Element) list.item(c))); 00165 00166 // then for each sub element in the root that is good, parse it 00167 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading locomotion"); 00168 list = root.getElementsByTagName(BehaviorType.LOCOMOTION.elementName); 00169 for (int c = 0; c < list.getLength(); c++) 00170 this.locomotions.add(new LocomotionBehavior(logger, (Element) list 00171 .item(c))); 00172 00173 // then for each sub element in the root that is good, parse it 00174 this.listLogger.debug(LoggerLevel.BEHAVIOR, "Loading speeches"); 00175 list = root.getElementsByTagName(BehaviorType.SPEECH.elementName); 00176 for (int c = 0; c < list.getLength(); c++) 00177 this.speeches 00178 .add(new SpeechBehavior(logger, (Element) list.item(c))); 00179 00180 // store the behaviors by id to retrieve them easily. 00181 for (Behavior b : this.emits) 00182 map.put(b.getID(), b); 00183 for (Behavior b : this.faces) 00184 map.put(b.getID(), b); 00185 for (Behavior b : this.gazes) 00186 map.put(b.getID(), b); 00187 for (Behavior b : this.gestures) 00188 map.put(b.getID(), b); 00189 for (Behavior b : this.heads) 00190 map.put(b.getID(), b); 00191 for (Behavior b : this.lips) 00192 map.put(b.getID(), b); 00193 for (Behavior b : this.locomotions) 00194 map.put(b.getID(), b); 00195 for (Behavior b : this.speeches) 00196 map.put(b.getID(), b); 00197 00198 this.listLogger.debug(LoggerLevel.BEHAVIOR, "BML loaded"); 00199 } 00200 00208 public BehaviorList(Logger logger, XMLInterface xml, String id) { 00209 this.xml = xml; 00210 this.id = id; 00211 this.listLogger = logger.sub(Colors.BEHAV_LIST, "LIST"); 00212 00213 this.requiredCons = new ConstraintBehavior(logger, id + "-req-cons", 00214 true); 00215 this.optionalCons = new ConstraintBehavior(logger, id + "-opt-cons", 00216 false); 00217 this.emits = new ArrayList<EmitBehavior>(); 00218 this.faces = new ArrayList<FaceBehavior>(); 00219 this.gazes = new ArrayList<GazeBehavior>(); 00220 this.gestures = new ArrayList<GestureBehavior>(); 00221 this.heads = new ArrayList<HeadBehavior>(); 00222 this.lips = new ArrayList<LipsBehavior>(); 00223 this.locomotions = new ArrayList<LocomotionBehavior>(); 00224 this.speeches = new ArrayList<SpeechBehavior>(); 00225 00226 this.map = new HashMap<String, Behavior>(); 00227 map.put(requiredCons.getID(), requiredCons); 00228 map.put(optionalCons.getID(), optionalCons); 00229 this.results = new ArrayList<BehaviorResult>(); 00230 } 00231 00235 public ConstraintBehavior getOptionalConstraints() { 00236 return optionalCons; 00237 } 00238 00242 public ConstraintBehavior getRequiredConstraints() { 00243 return requiredCons; 00244 } 00245 00249 public List<EmitBehavior> getEmits() { 00250 return emits; 00251 } 00252 00256 public List<FaceBehavior> getFaces() { 00257 return faces; 00258 } 00259 00263 public List<GazeBehavior> getGazes() { 00264 return gazes; 00265 } 00266 00270 public List<GestureBehavior> getGestures() { 00271 return gestures; 00272 } 00273 00277 public List<HeadBehavior> getHeads() { 00278 return heads; 00279 } 00280 00284 public List<LipsBehavior> getLips() { 00285 return lips; 00286 } 00287 00291 public List<LocomotionBehavior> getLocomotions() { 00292 return locomotions; 00293 } 00294 00298 public List<SpeechBehavior> getSpeeches() { 00299 return speeches; 00300 } 00301 00307 public List<Behavior> getAllBehaviors() { 00308 ArrayList<Behavior> all = new ArrayList<Behavior>(); 00309 all.add(this.requiredCons); 00310 all.add(this.optionalCons); 00311 all.addAll(this.emits); 00312 all.addAll(this.faces); 00313 all.addAll(this.gazes); 00314 all.addAll(this.gestures); 00315 all.addAll(this.heads); 00316 all.addAll(this.lips); 00317 all.addAll(this.locomotions); 00318 all.addAll(this.speeches); 00319 00320 return all; 00321 } 00322 00323 @Override 00324 public Iterator<Behavior> iterator() { 00325 return this.getAllBehaviors().iterator(); 00326 } 00327 00333 public String getID() { 00334 return this.id; 00335 } 00336 00344 public Behavior find(String id) { 00345 return map.get(id); 00346 } 00347 00359 public void addFinished(String id, SyncPoint point, byte result) { 00360 BehaviorResult finished = new BehaviorResult(); 00361 finished.behavior = new ros.pkg.bml_msgs.msg.Behavior(); 00362 finished.behavior.id = id; 00363 finished.behavior.synchPoint = (point == null) ? SyncPoint.END.rosValue 00364 : point.rosValue; 00365 finished.result = new Flag(); 00366 finished.result.value = result; 00367 this.results.add(finished); 00368 } 00369 00375 public ArrayList<BehaviorResult> getFinished() { 00376 return this.results; 00377 } 00378 00384 public int size() { 00385 // the 2 is for the constraint behaviors 00386 return 2 + this.emits.size() + this.faces.size() + this.gazes.size() 00387 + this.gestures.size() + this.heads.size() + this.lips.size() 00388 + this.locomotions.size() + this.speeches.size(); 00389 } 00390 00399 public String toBML() { 00400 Document doc = this.xml.createDocument(); 00401 Element root = doc.createElement("bml"); 00402 root.setAttribute("id", this.id); 00403 doc.appendChild(root); 00404 00405 // then for each behavior which is not a reference, convert it to BML. 00406 for (Behavior behav : this.getAllBehaviors()) 00407 root.appendChild(behav.toBML(doc)); 00408 00409 return this.xml.convertDocumentToString(doc); 00410 } 00411 00428 public static BehaviorList parseBML(Logger logger, XMLInterface xml, 00429 String bml) { 00430 Document doc = xml.loadDocument(new StringReader(bml)); 00431 return new BehaviorList(logger, xml, doc.getDocumentElement()); 00432 } 00433 } |