/* * (c) 2000-2009 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved. * Licencia en license/bsd.txt / License in license/bsd.txt */ package eu.irreality.age; //package AetheriaAWT; /** * Entidades que pueblan el mundo. * Definimos "entidad" como "objeto del mundo de Aetheria que es afectado por el paso del tiempo". * Cada entidad est�, en cada momento, en un estado, y puede cambiar de estado seg�n las circunstancias. * Entidades son las habitaciones, los items, los enemigos y el personaje. * * @author Carlos G�mez */ import java.util.*; import eu.irreality.age.debug.Debug; import eu.irreality.age.debug.ExceptionPrinter; import eu.irreality.age.scripting.ScriptException; public abstract class Entity { List propertiesList = new ArrayList(); //of PropertyEntry protected Vector relationships = new Vector(); //vector of Entity protected Vector relationship_properties = new Vector(); //vector of List of Property /**Estado actual*/ //protected int state; /**Unidades restantes para cambiar de estado*/ //protected long timeUnitsLeft; /**Blanco de los estados*/ //protected int target; //para los diferentes clone() de las subclases de Entity. Coge los campos de e. public void copyEntityFields(Entity e) { //Debug.println("CLONING ENTITY FIELDS from Source " + (((Item)e).getTitle()) + ":" + e.getID()); //Debug.println("SOURCE HAS " + e.propertiesList.size() + " properties, " + e.relationships.size() + " relationships" ); propertiesList = new ArrayList ( e.propertiesList.size() ); for ( int i = 0 ; i < e.propertiesList.size() ; i++ ) { propertiesList.add ( ((PropertyEntry)e.propertiesList.get(i)).clone() ); } relationships = new Vector( e.relationships.size() ); for ( int i = 0 ; i < e.relationships.size() ; i++ ) { relationships.add ( ((Entity)e.relationships.get(i)) ); } relationship_properties = new Vector ( e.relationship_properties.size() ); for ( int i = 0 ; i < e.relationship_properties.size() ; i++ ) { List ofProperties = new ArrayList( ((List)e.relationship_properties.get(i)).size() ); relationship_properties.add(ofProperties); for ( int j = 0 ; j < ofProperties.size() ; j++ ) { ofProperties.add ( ((PropertyEntry)((List)e.relationship_properties.get(i)).get(j)).clone() ); } } } /** * update: funci�n gen�rica que hace pasar una unidad de tiempo y actualiza el estado si es necesario. * * @return true si sale bien el update. */ public boolean update(World mundo) { //si se ha solicitado que alguna propiedad sea puesta delante en la lista if ( pushToFront.size() > 0 ) pushRequestedPropertiesToFront (); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); //if ( this instanceof Player ) Debug.println(pe.getName()+" isat " +i); pe.decreaseTime(); if ( pe.needsUpdate() ) { //if ( pe.getName().equalsIgnoreCase("state") ) //{ //Debug.println("changeState called by " + this); // changeState( mundo ); //legacy!! //} //nah, changeState called by update. //else //{ update ( pe , mundo ); //} } } for ( int i = 0 ; i < relationships.size() ; i++ ) { Entity ent = (Entity) relationships.get(i); List propertyEntries = (List) relationship_properties.get(i); for ( int j = 0 ; j < propertyEntries.size() ; j++ ) { PropertyEntry entrada = (PropertyEntry) propertyEntries.get(j); entrada.decreaseTime(); if ( entrada.needsUpdate() ) { updateRelationship ( ent , entrada , mundo ); } } } return true; } //important /* public boolean update ( PropertyEntry pe , World mundo ) { boolean ejecutado = false; //try to exec entity's update function if ( this instanceof SupportingCode ) { SupportingCode esto = (SupportingCode) this; try { ejecutado = esto.execCode( "update" , new Object[] { pe , mundo } ); } catch (bsh.TargetError bshte) { mundo.escribir("bsh.TargetError found at update routine" ); bshte.printStackTrace(); } if ( ejecutado ) return true; //end() found } if ( this instanceof Player ) Debug.println("Checkpoint1"); //try to exec world's update function try { ejecutado = mundo.execCode( "update" , new Object[] { pe , this } ); } catch (bsh.TargetError bshte) { mundo.escribir("bsh.TargetError found at update routine" ); bshte.printStackTrace(); } if ( ejecutado ) return true; //end() found if ( pe.getName().equalsIgnoreCase("state") ) { if ( this instanceof Player ) Debug.println(this + "Changestate"); changeState( mundo ); //legacy!! } //else, should be overridden if it should do somethin' return true; } */ public boolean update ( PropertyEntry pe , World mundo ) { /* if ( this instanceof Player ) { Debug.println("Player update: " + pe.getName() + ":" + pe.getValue() + ":" + pe.getTimeLeft() ); } */ //Debug.println("UPDATE " + pe.getName()); /* if ( pe.getName().equalsIgnoreCase("state") ) { if ( this instanceof Player ) Debug.println(this + "Changestate"); Debug.println("'NNA CALL CHANGESTATE for " + this); changeState( mundo ); //legacy!! } */ /* if ( getID() == 20000007 ) { Mobile m = (Mobile)this; if ( m.getTitle().equalsIgnoreCase("Zunius") ) { Debug.println("Zun1"); } } */ //ON HANG, USE THIS CHSTATE INSTD. OF LAST ONE /* if ( pe.getName().equalsIgnoreCase("state") ) { //Debug.println("changeState called by " + this); changeState( mundo ); //legacy!! } */ /* if ( getID() == 20000007 ) { Mobile m = (Mobile)this; if ( m.getTitle().equalsIgnoreCase("Zunius") ) { Debug.println("Zun2"); } } */ if ( pe.getTimeLeft() < -1 ) return false; /* if ( getID() == 20000007 ) { Mobile m = (Mobile)this; if ( m.getTitle().equalsIgnoreCase("Zunius") ) { Debug.println("Zun3"); } } */ //else //{ //temp code copied from above boolean ejecutado = false; //try to exec entity's update function if ( this instanceof SupportingCode ) { SupportingCode esto = (SupportingCode) this; try { ejecutado = esto.execCode( "update" , new Object[] { pe , mundo } ); } catch (ScriptException bshte) { mundo.write(mundo.getIO().getColorCode("error")); mundo.write("bsh.TargetError found at update routine, entity is " + this + ", property entry is " + pe.getName() + "\n" ); mundo.write("Target exception: " + bshte.printTargetError(bshte.getTarget()) + "\n" ); mundo.writeError(ExceptionPrinter.getExceptionReport(bshte)); mundo.write(mundo.getIO().getColorCode("reset")); bshte.printStackTrace(); } if ( ejecutado ) return true; //end() found } //if ( this instanceof Player ) // Debug.println("Checkpoint1"); //Debug.println("Ejecutado at cp1 is " + ejecutado); //try to exec world's update function try { ejecutado = mundo.execCode( "update" , new Object[] { pe , this } ); } catch (ScriptException bshte) { mundo.write("bsh.TargetError found at world's update routine, property entry is " + pe.getName() ); mundo.writeError(ExceptionPrinter.getExceptionReport(bshte)); bshte.printStackTrace(); } if ( ejecutado ) return true; //end() found //Debug.println("Ejecutado is " + ejecutado); if ( pe.getName().equalsIgnoreCase("state") ) { //Debug.println("changeState called by " + this); changeState( mundo ); //legacy!! } //} return true; } public /*abstract*/ boolean updateRelationship ( Entity e , PropertyEntry pe , World mundo ) { return true; } public List getProperties () { return propertiesList; } public String getPropertyValue ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValue(); } return null; } public String getPropertyValueAsString ( String propertyName ) { return getPropertyValue ( propertyName ); } private List pushToFront = new ArrayList(); //propiedades que tenemos que poner delante. //No se ponen inmediatamente con la funci�n pushPropertyToFront() porque �sta //tender� a ser llamada desde cosas que se hagan dentro de un update() [que es //donde normalmente se actualizan propiedades] y no nos interesa que el orden //de la lista cambie en medio del update, sino al final. //En ocasiones, nos interesar� que unas prioridades se actualicen antes que otras. //Con esto, damos a una m�xima prioridad. public void pushPropertyToFront ( String propertyName ) { pushToFront.add ( propertyName ); } private void pushRequestedPropertiesToFront ( ) { for ( int i = 0 ; i < pushToFront.size() ; i++ ) { pushPropertyToFrontReally ( (String)pushToFront.get(i) ); } pushToFront = new ArrayList(); } private void pushPropertyToFrontReally ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) { propertiesList.remove(pe); propertiesList.add(0,pe); } } } public Object getPropertyValueAsObject ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsObject(); } return null; } public boolean getPropertyValueAsBoolean ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsBoolean(); } return false; } public int getPropertyValueAsInteger ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsInteger(); } return 0; } public double getPropertyValueAsDouble ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsDouble(); } return 0; } public float getPropertyValueAsFloat ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsFloat(); } return 0; } public Object getPropertyValueAsWrapper ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsWrapper(); } return null; } public long getPropertyTimeLeft ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getTimeLeft(); } return 0; } public void setPropertyTimeLeft ( String propertyName , long newTime ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) pe.setTime(newTime); } } public PropertyEntry getPropertyEntry ( String propertyName ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe; } return null; } public void setProperty ( String propertyName , String propertyValue ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) { pe.setValue ( propertyValue ); return; } } //property not found, add to list propertiesList.add ( new PropertyEntry ( propertyName , propertyValue , -1 ) ); } //notese que si se pasa como segundo parametro un String no se llamara //esta funcion, sino setProperty ( String , String ) por ser mas especifica. public void setProperty ( String propertyName , Object propertyValue ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) { pe.setValue ( propertyValue.toString() ); pe.setObjectValue ( propertyValue ); return; } } PropertyEntry pe = new PropertyEntry ( propertyName , propertyValue.toString() , -1 ); pe.setObjectValue ( propertyValue ); propertiesList.add ( pe ); } public void setProperty ( String propertyName , int propertyValue ) { setProperty ( propertyName , String.valueOf(propertyValue) ); } public void setProperty ( String propertyName , double propertyValue ) { setProperty ( propertyName , String.valueOf(propertyValue) ); } public void setProperty ( String propertyName , float propertyValue ) { setProperty ( propertyName , String.valueOf(propertyValue) ); } public void setProperty ( String propertyName , boolean propertyValue ) { setProperty ( propertyName , String.valueOf(propertyValue) ); } public void setProperty ( String propertyName , String propertyValue , long timeLeft ) { for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) { pe.setValueAndTime ( propertyValue , timeLeft ); return; } } //property not found, add to list propertiesList.add ( new PropertyEntry ( propertyName , propertyValue , timeLeft ) ); } public void setProperty ( String propertyName , int propertyValue , long timeLeft ) { setProperty ( propertyName , String.valueOf(propertyValue) , timeLeft ); } public void setProperty ( String propertyName , boolean propertyValue , long timeLeft ) { setProperty ( propertyName , String.valueOf(propertyValue) , timeLeft ); } public boolean hasBooleanProperty ( String propertyName ) { return getPropertyValueAsBoolean ( propertyName ); } /** * Nos dice si se da por aludido el objeto ante un comando (ej. "mirar piedra") -> se pasa "piedra") * * @param commandArgs Los argumentos del comando. * @param pluralOrSingular 1 si plural. * @return 0 si no se da por aludido, 1 si s�, y con qu� prioridad. (+ n� = - prioridad). La prioridad es el orden que ocupa el nombre que se corresponde con el comando dado en la lista de nombres. */ public int matchesCommand ( String commandArgs , boolean pluralOrSingular ) { return 0; //s�lo algunas clases de Entity, las que se puedan agrupar en listas, necesitar�n overridear este m�todo. } /** * This implements one of the modes of matchesCommand ( String , String ) * @param commandArgs arguments of a command that might refer to this object * @param referenceList ordered list of reference names * @return 0 si no se da por aludido, 1 si s�, y con qu� prioridad. (+ n� = - prioridad). La prioridad es el orden que ocupa el nombre que se corresponde con el comando dado en la lista de nombres. */ protected int legacyMatchesCommand ( String commandArgs , List referenceNameList ) { int nToksArg = StringMethods.numToks( commandArgs , ' '); //int nToksList = StringMethods.numToks( referenceNameList , '$'); for ( int i = 1 ; i <= nToksArg ; i++ ) { String currentToAnalyze = StringMethods.getToks( commandArgs , i , nToksArg , ' ' ); //"mirar la piedra peque�a" -> commandArgs="la piedra peque�a" -> vamos analizando "la piedra peque�a", "piedra peque�a", ... //for ( int j = 1 ; j <= nToksList ; j++ ) for ( int j = 0 ; j < referenceNameList.size() ; j++ ) { //if ( StringMethods.getTok( referenceNameList , j , '$' ) .equalsIgnoreCase(currentToAnalyze) ) // return j; if ( ((String)referenceNameList.get(j)).equalsIgnoreCase(currentToAnalyze) ) return j+1; } //TODO: here, add reverse analysis. gettoks from 1 to moving i. } return 0; } /** * New matchesCommand mode implemented 2010-06-25, more robust than the "legacy" mode that wouldn't accept anything * to the right of entities. * @param commandArgs * @param referenceNameList * @return */ protected int lenientMatchesCommand ( String commandArgs , List referenceNameList ) { //StringTokenizer st = new StringTokenizer ( referenceNameList , "$" ); Iterator it = referenceNameList.iterator(); int j = 0; //current token being read, starting at 1 (we set to 0 here because we're going to do j++ inside the while loop) //while ( st.hasMoreTokens() ) while ( it.hasNext() ) { j++; String currentReferenceName = //st.nextToken(); (String) it.next(); if ( commandArgs.toLowerCase().contains(currentReferenceName.toLowerCase()) ) return j; } return 0; /* int nToksList = StringMethods.numToks( referenceNameList , '$'); for ( int j = 1 ; j <= nToksList ; j++ ) { String currentReferenceName = StringMethods.getTok( referenceNameList , j , '$' ); if ( commandArgs.toLowerCase().contains(currentReferenceName.toLowerCase()) ) return j; } return 0; */ } /** * New matchesCommand mode implemented 2011-05-01, a bit less lenient than the lenient matchesCommand. Will search for * matches with words. * @param commandArgs * @param referenceNameList * @return */ protected int moderateMatchesCommand ( String commandArgs , List referenceNameList ) { //StringTokenizer st = new StringTokenizer ( referenceNameList , "$" ); Iterator it = referenceNameList.iterator(); int j = 0; //current token being read, starting at 1 (we set to 0 here because we're going to do j++ inside the while loop) //while ( st.hasMoreTokens() ) while ( it.hasNext() ) { j++; String currentReferenceName = // st.nextToken(); (String) it.next(); int position = commandArgs.toLowerCase().indexOf(currentReferenceName.toLowerCase()); if ( position < 0 ) //does not match continue; if ( position != 0 && !Character.isWhitespace(commandArgs.charAt(position-1)) ) //matches but starts at a place other than beginning/whitespace continue; if ( position+currentReferenceName.length() != commandArgs.length() && !Character.isWhitespace(commandArgs.charAt(position+currentReferenceName.length())) ) //matches but ends at a place other than end/whitespace continue; //if we have reached this point, the match is acceptable return j; } return 0; /* int nToksList = StringMethods.numToks( referenceNameList , '$'); for ( int j = 1 ; j <= nToksList ; j++ ) { String currentReferenceName = StringMethods.getTok( referenceNameList , j , '$' ); int position = commandArgs.toLowerCase().indexOf(currentReferenceName.toLowerCase()); if ( position < 0 ) //does not match continue; if ( position != 0 && !Character.isWhitespace(commandArgs.charAt(position-1)) ) //matches but starts at a place other than beginning/whitespace continue; if ( position+currentReferenceName.length() != commandArgs.length() && !Character.isWhitespace(commandArgs.charAt(position+currentReferenceName.length())) ) //matches but ends at a place other than end/whitespace continue; //if we have reached this point, the match is acceptable return j; } return 0; */ } /** * Note: takes a legacy, $-separated list of reference names * This method may be called by subclass-specific implementations of the matchesCommand ( String , boolean ) method. * @param commandArgs arguments of a command that might refer to this object * @param referenceList ordered list of reference names * @return 0 si no se da por aludido, 1 si s�, y con qu� prioridad. (+ n� = - prioridad). La prioridad es el orden que ocupa el nombre que se corresponde con el comando dado en la lista de nombres. */ protected int matchesCommand ( String commandArgs , List referenceNameList , int commandMatchingMode ) { if ( commandMatchingMode == LEGACY_COMMAND_MATCHING ) return legacyMatchesCommand ( commandArgs , referenceNameList ); else if ( commandMatchingMode == LENIENT_COMMAND_MATCHING ) return lenientMatchesCommand ( commandArgs , referenceNameList ); else return moderateMatchesCommand ( commandArgs , referenceNameList ); } //command matching modes public static final int LEGACY_COMMAND_MATCHING = 0; public static final int LENIENT_COMMAND_MATCHING = 1; public static final int MODERATE_COMMAND_MATCHING = 2; /**Funciones que manejan esa propiedad tan especial que es el estado, que antes era la �nica que hab�a.**/ public void setNewTarget ( int ntarget ) { setProperty ( "target" , ntarget ); } public int getTarget ( ) { return getPropertyValueAsInteger("target"); } public void setNewState ( int nstate , long TUs ) { if ( getPropertyValueAsInteger ("state") == Mobile.CASTING ) { //Debug.println("setNewState: "); //(new Exception()).printStackTrace(); } setProperty ( "state" , nstate , TUs ); } protected void setNewState ( int nstate ) { setProperty ( "state" , nstate ); } public int getState ( ) { return getPropertyValueAsInteger("state"); } /** * Hace todo lo necesario para el cambio de estado. * */ public abstract void changeState ( World mundo ); /** * Devuelve true si el estado tiene los bits a 1 en la m�scara iguales que el comparando. * */ public boolean stateMatches ( int comparand , int mask ) { return (( mask & ( getPropertyValueAsInteger("state") ^ comparand ) ) == 0 ); } /** * Create and return the XML representation for a name list. Used for reference names. * @param doc The document in which to create the XML element. * @param inputList List of Strings with names, e.g. reference names. * @param outputElementName Name of the XML element containing the name list. * @return */ public org.w3c.dom.Element getNameListXMLRepresentation ( org.w3c.dom.Document doc , List inputList , String outputElementName ) { org.w3c.dom.Element respTo = doc.createElement(outputElementName); Iterator it = inputList.iterator(); while ( it.hasNext() ) { String tok = (String) it.next(); org.w3c.dom.Element esteNombre = doc.createElement("Name"); org.w3c.dom.Text elNombre = doc.createTextNode(tok); esteNombre.appendChild(elNombre); respTo.appendChild(esteNombre); } return respTo; } public org.w3c.dom.Node getPropListXMLRepresentation ( org.w3c.dom.Document doc ) { org.w3c.dom.Element e = doc.createElement("PropertyList"); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); org.w3c.dom.Node nodoProp = pe.getXMLRepresentation(doc); e.appendChild (nodoProp); } return e; } //n es el nodo asociado a la entidad. public void readPropListFromXML ( World mundo , org.w3c.dom.Node n ) throws XMLtoWorldException { org.w3c.dom.Element e = null; try { e = (org.w3c.dom.Element) n; } catch ( ClassCastException cce ) { throw ( new XMLtoWorldException ( "Entity node not Element" ) ); } org.w3c.dom.NodeList nl = e.getElementsByTagName("PropertyList"); if ( nl.getLength() <= 0 ) //propertiesList = new ArrayList(); ; //esto ya est� por defecto (inicializaci�n atr) else { org.w3c.dom.Element elementoPropertyList = (org.w3c.dom.Element) nl.item(0); org.w3c.dom.NodeList listaPropertyEntries = elementoPropertyList.getElementsByTagName("PropertyEntry"); for ( int i = 0 ; i < listaPropertyEntries.getLength() ; i++ ) { org.w3c.dom.Node nod = listaPropertyEntries.item(i); PropertyEntry pe = new PropertyEntry ( mundo , nod ); //si la propiedad ya estaba presente, quitar la copia presente. //esto puede suceder porque esta funcion se llame mas de una vez //debido a la herencia, y nos interesa que las propiedades se sobreescriban. String nombre = pe.getName(); for ( int j = propertiesList.size()-1 ; j >= 0 ; j-- ) { PropertyEntry actual = (PropertyEntry) propertiesList.get(j); if ( actual.getName().equals(nombre) ) propertiesList.remove(actual); } propertiesList.add(pe); } } } public abstract int getID(); //begin //relationship-related functions /* Las relaciones con estado entre m�viles y otros objetos (o tal vez, en el futuro, entre entidades en general, si hiciera falta?) resultan �tiles. Gracias a ellas, un jugador puede, por ejemplo, "recordar" lo que hab�a en una habitaci�n: al mirarla se establece un estado 1 (por ejemplo) en su relaci�n con esa entidad habitaci�n, de tal modo que cuando vuelve a ella ya no tiene que "buscar" algo sino que lo ve directamente, por ejemplo. No para cambios objetivos en la habitaci�n que ver�a cualquiera (como el que se abra una puerta) */ public org.w3c.dom.Node getRelationshipListXMLRepresentation ( org.w3c.dom.Document doc ) { org.w3c.dom.Element e = doc.createElement ( "RelationshipList" ); for ( int i = 0 ; i < relationships.size() ; i++ ) { org.w3c.dom.Element eRel = doc.createElement ( "Relationship" ); org.w3c.dom.Element ePropList = doc.createElement ( "PropertyList" ); Entity objetivo = (Entity) relationships.elementAt(i); eRel.setAttribute ( "id" , String.valueOf( objetivo.getID() ) ); List propertiesList = (List) relationship_properties.elementAt(i); for ( int j = 0 ; j < propertiesList.size() ; j++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(j); org.w3c.dom.Node nodoProp = pe.getXMLRepresentation(doc); ePropList.appendChild (nodoProp); } eRel.appendChild ( ePropList ); e.appendChild ( eRel ); } return e; } //pasar directamente como parametro el nodo del Mobile. //esto es para carga DIFERIDA!! Son entitys, no sabemos si de las que se cargan antes o despu�s. public void readRelationshipListFromXML ( World mundo , org.w3c.dom.Node n ) throws XMLtoWorldException { if ( ! ( n instanceof org.w3c.dom.Element ) ) throw ( new XMLtoWorldException ( "Mobile node not Element" ) ); org.w3c.dom.Element e = ( org.w3c.dom.Element) n; org.w3c.dom.NodeList nl = e.getElementsByTagName("RelationshipList"); if ( nl.getLength() <= 0 ) ; //no hacemos nada porque relationships y cia ya son un new Vector() else { org.w3c.dom.Element relationshipListNode = (org.w3c.dom.Element) nl.item(0); org.w3c.dom.NodeList relaciones = relationshipListNode.getElementsByTagName("Relationship"); for ( int i = 0 ; i < relaciones.getLength() ; i++ ) { org.w3c.dom.Element thisRelationshipNode = (org.w3c.dom.Element)relaciones.item(i); //get relationship target (id) if ( ! (thisRelationshipNode.hasAttribute("id")) ) throw ( new XMLtoWorldException ( "Relationship node lacking attribute id" ) ); relationships.add ( mundo.getObject ( thisRelationshipNode.getAttribute("id") ) ); //get relationship property list org.w3c.dom.NodeList pListNodes = thisRelationshipNode.getElementsByTagName("PropertyList"); List propertiesList; if ( pListNodes.getLength() < 0 ) propertiesList = new ArrayList(); else { propertiesList = new ArrayList(); org.w3c.dom.Element elementoPropertyList = (org.w3c.dom.Element) pListNodes.item(0); org.w3c.dom.NodeList listaPropertyEntries = elementoPropertyList.getElementsByTagName("PropertyEntry"); for ( int k = 0 ; k < listaPropertyEntries.getLength() ; k++ ) { org.w3c.dom.Node nod = listaPropertyEntries.item(k); PropertyEntry pe = new PropertyEntry ( mundo , nod ); propertiesList.add(pe); } } relationship_properties.add ( propertiesList ); } } //end else if length > 0 [has relationships] } //end method public int getRelationshipState ( Entity e ) { return getRelationshipPropertyValueAsInteger ( e , "state" ); } public int getRelationshipPropertyValueAsInteger ( Entity e , String propertyName ) { int lim = relationships.size(); for ( int k = 0 ; k < lim ; k++ ) { if ( relationships.elementAt(k).equals(e) ) { //lista de propiedades de la relaci�n List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsInteger(); } } } return 0; //by default } public Object getRelationshipPropertyValueAsWrapper ( Entity e , String propertyName ) { int lim = relationships.size(); for ( int k = 0 ; k < lim ; k++ ) { if ( relationships.elementAt(k).equals(e) ) { //lista de propiedades de la relaci�n List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsWrapper(); } } } return null; //by default } public String getRelationshipPropertyValueAsString ( Entity e , String propertyName ) { Debug.println("Relationships size is " + relationships.size() ); int lim = relationships.size(); for ( int k = 0 ; k < lim ; k++ ) { Debug.println("Checking a relationship. Entity: " + e.getID()); if ( relationships.elementAt(k).equals(e) ) { Debug.println("Entity found."); //lista de propiedades de la relaci�n List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { Debug.println("Name: " + ((PropertyEntry) propertiesList.get(i)).getName()); PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValue(); } } } return null; //by default } public List getRelatedEntities ( String propertyName ) { int lim = relationships.size(); List result = new ArrayList(); for ( int k = 0 ; k < lim ; k++ ) { Entity other = (Entity) relationships.elementAt(k); List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) { result.add ( other ); break; } } } return result; } public List getRelatedEntitiesByValue ( String propertyName , boolean boolVal ) { int lim = relationships.size(); List result = new ArrayList(); for ( int k = 0 ; k < lim ; k++ ) { Entity other = (Entity) relationships.elementAt(k); List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) && pe.getValueAsBoolean() == boolVal ) { result.add ( other ); break; } } } return result; } public List getRelatedEntitiesByValue ( String propertyName , int intVal ) { int lim = relationships.size(); List result = new ArrayList(); for ( int k = 0 ; k < lim ; k++ ) { Entity other = (Entity) relationships.elementAt(k); List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) && pe.getValueAsInteger() == intVal ) { result.add ( other ); break; } } } return result; } public boolean getRelationshipPropertyValueAsBoolean ( Entity e , String propertyName ) { int lim = relationships.size(); for ( int k = 0 ; k < lim ; k++ ) { if ( relationships.elementAt(k).equals(e) ) { //lista de propiedades de la relaci�n List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) return pe.getValueAsBoolean(); } } } return false; //by default } public void setRelationshipProperty ( Entity e , String propertyName , String propertyValue ) { int lim = relationships.size(); //Debug.println("On setting string relationship property " + propertyName + ", size is " + relationships.size()); for ( int k = 0 ; k < lim ; k++ ) { if ( relationships.elementAt(k).equals(e) ) { List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) { pe.setValue ( propertyValue ); return; } } //property not found, add to list propertiesList.add ( new PropertyEntry ( propertyName , propertyValue , -1 ) ); return; } } //relationship not found, add to relationships relationships.addElement ( e ); List nuevaPropEntryList = new ArrayList(); PropertyEntry pe = new PropertyEntry( propertyName , propertyValue , 0 ); nuevaPropEntryList.add(pe); relationship_properties.addElement(nuevaPropEntryList); return; } //creo que se puede eliminar y dejar s�lo el de String, hacen the same public void setRelationshipProperty ( Entity e , String propertyName , Object propertyValue ) { int lim = relationships.size(); for ( int k = 0 ; k < lim ; k++ ) { if ( relationships.elementAt(k).equals(e) ) { List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) { pe.setValue ( propertyValue ); return; } } //property not found, add to list PropertyEntry pe = new PropertyEntry ( propertyName , propertyValue.toString() , -1 ); pe.setObjectValue(propertyValue); propertiesList.add ( pe ); return; } } //relationship not found, add to relationships relationships.addElement ( e ); List nuevaPropEntryList = new ArrayList(); PropertyEntry pe = new PropertyEntry( propertyName , propertyValue.toString() , 0 ); pe.setObjectValue(propertyValue); nuevaPropEntryList.add(pe); relationship_properties.addElement(nuevaPropEntryList); return; } public void setRelationshipProperty ( Entity e , String propertyName , int propertyValue ) { //Debug.println("On setting int relationship property " + propertyName + ", size is " + relationships.size()); setRelationshipProperty ( e , propertyName , String.valueOf ( propertyValue ) ); //Debug.println("After setting int relationship property " + propertyName + ", size is " + relationships.size()); } public void setRelationshipProperty ( Entity e , String propertyName , boolean propertyValue ) { //Debug.println("On setting bool relationship property " + propertyName + ", size is " + relationships.size()); setRelationshipProperty ( e , propertyName , String.valueOf ( propertyValue ) ); //Debug.println("After setting bool relationship property " + propertyName + ", size is " + relationships.size()); } public void setRelationshipPropertyTimeLeft ( Entity e , String propertyName , long newtime ) { int lim = relationships.size(); //Debug.println("On setting string relationship property " + propertyName + ", size is " + relationships.size()); for ( int k = 0 ; k < lim ; k++ ) { if ( relationships.elementAt(k).equals(e) ) { List propertiesList = (List) relationship_properties.elementAt(k); for ( int i = 0 ; i < propertiesList.size() ; i++ ) { PropertyEntry pe = (PropertyEntry) propertiesList.get(i); if ( pe.getName().equalsIgnoreCase(propertyName) ) { pe.setTime ( newtime ); return; } } //property not found, add to list propertiesList.add ( new PropertyEntry ( propertyName , "false" , newtime ) ); return; } } //relationship not found, add to relationships relationships.addElement ( e ); List nuevaPropEntryList = new ArrayList(); PropertyEntry pe = new PropertyEntry( propertyName , "false" , newtime ); nuevaPropEntryList.add(pe); relationship_properties.addElement(nuevaPropEntryList); return; } public void setRelationshipState ( Entity e , int newState ) { setRelationshipProperty ( e , "state" , newState ); } public String toString() { String s = ("[ " + getClass().getName() + ":" + getID() ); //changed 2011-09-25 /* if ( this instanceof Nameable ) { s += ":"; s += ((Nameable)this).constructName2(1,null); } */ if ( this instanceof UniqueNamed ) { s += ":"; s += ((UniqueNamed)this).getUniqueName(); } s+=" ]"; return s; } //end //relationship-related functions // // }