29 de MAYO de 2002

Anuncio
INGENIERÍA DEL SOFTWARE. 4º ING. INFORMÁTICA (UPV/EHU)
29 de MAYO de 2002
NOMBRE:
GRUPO:
1.- (0,5 ptos.) (Tiempo estimado: 10’) Enuncia cuáles son las interfaces que se tienen que definir
para desarrollar un EJB, así como cuál es su finalidad.
La interfaz home: Tiene la signatura de los métodos para
crear/destruir objetos EJB.
La interfaz remota: La interfaz con la que opera el cliente cuando
quiere invocar al EJB.
La interfaz local: tiene la misma funcionalidad que la interfaz
remota. Sin embargo esta interfaz será utilizada únicamente cuando
el cliente y el objeto que implementa esta interfaz estén en la
misma má quina.
La interfaz local home: tiene la misma funcionalidad que la interfaz
home. Se utilizará en el mismo contexto que la interfaz anterior.
2.- (0,5 ptos.) (Tiempo estimado: 10’) Explica qué son los RESGUARDOS y los
CONTROLADORES, y su relación con los COMPONENTES y PROCEDIMIENTOS DE
PRUEBA
RESGUARDO: módulo que sustituye a otro módulo real llamado desde el
módulo que se está probando (pruebas con integración descendente).
CONTROLADOR: módulo que llama a un módulo real a probar con los
datos de entrada especificados en distintos casos de prueba (pruebas
con INTEGRACIÓN ASCENDENTE). Los COMPONENTES y PROCEDIMIENTOS DE
PRUEBA son artefactos utilizados en el Proceso Unificado. Un
procedimiento de prueba especifica cómo realizar uno o varios casos
de prueba y los componentes de prueba automatizan procedimientos de
prueba, si es posible. Podríamos decir que el concepto de
controlador y el de componente de prueba es el mismo.
3.- (2,5 ptos.) (Tiempo estimado: 40’) Queremos trabajar con una especie de base de datos
utilizando JGL. Para ello, se utilizará un Container JGL para almacenar las “tuplas” y el
siguiente algoritmo JGL para realizar consultas de selección:
Filtering.select(Container, UnaryPredicate)
El predicado JGL UnaryPredicate se utiliza para expresar la condición de la selección. Se
pueden realizar preguntas con condiciones compuestas con el siguiente UnaryPredicate:
UnaryAnd(UnaryPredicate, UnaryPredicate)
En concreto, se puede conseguir la conjunción lógica de dos predicados, esto es, que se devuelva
true si y sólo si ambos predicados devuelven true.
Para visualizar los resultados podemos utilizar este otro algoritmo JGL , que aplica una función
a todos los elementos del Container.
Applying.forEach(Container, UnaryFunction)
A continuación se presenta el diseño de tres clases: Empleado, Becario y Profesor y el código
INCOMPLETO de una clase Principal que visualiza la respuesta a la siguiente consulta:
CONSULTA: encontrar todos los profesores que ganan más de 150.000 y que son de Lezo
Empleado
-nombre : String
-diasTrabajados : int
-sueldoDiario- : double
-ciudad : String
+getSueldo() : double
+toString() : String
Becario
Profesor
-proyecto : String
-departamento : String
+toString() : String
+toString() : String
// Omitimos los imports de JGL
public class Principal {
public static void main (String[] args) {
double topeSueldo = 150000.0;
String ciudad = "Lezo";
Container datos = new Array();
datos.add(new
datos.add(new
datos.add(new
datos.add(new
Becario("Leizarraga",20.0, 1300.0, "Aduna","UPV-EHU") );
Becario("Lizarralde",25.0,1200.0, "Lekeitio","DIPU"));
Profesor("Fernandez",120.0, 3000.0, "Lezo","LSI") );
Profesor("Zelaia",50.0, 4000.0, "Lezo","ATC") );
UnaryPredicate profesor
UnaryPredicate sueldo
UnaryPredicate ciudadano
= new InstanciaDeProfesor();
= new TopesSueldo(topeSueldo);
= new CiudadanoDe(ciudad);
Container resultado = Filtering.select(?????, ??????);
// Usar Applying.forEach(??????, ??????) para visualizar datos
} }
fin de la clase Principal
Se pide: realizar la implementación de las clases necesarias y completar la clase Principal.
SOLUCIÓN:
UnaryPredicate ciudadano =
new BindSecondPredicate(new EqualString(),”Lezo”);
UnaryPredicate sueldo
=
new BindSecondPredicate(new GreaterNumber(),150000);
UnaryPredicate profesor= new EsProfesor();
UnaryPredicate up1=new UnaryAnd(profesor, sueldo);
UnaryPredicate up2=new UnaryAnd(up1,ciudadano);
UnaryFunction ver=new VerDatos();
Container resultado = Filtering.select(datos, up2);
Applying.forEach(resultado, ver);
class EsProfesor implements UnaryPredicate {
public boolean execute(o) {
return o.instanceOf(Profesor);
}
}
class VerDatos implements UnaryFunction {
public void execute(o) {
Empleado emp=(Empleado)o;
System.out.println(emp.nombre+” “+emp .ciudad+” “+emp.sueldo);
}
}
4.- (3 ptos.) (Tiempo estimado: 45’) El diagrama de secuencia con el diseño del caso de uso
“Buscar Personas Por Nombre”
Buscar Personas
Por Nombre
Usuario
es el siguiente:
: IU_VP
GBD: Statement
: GestorPersonas
usuario
escribir Nombre()
buscarPorNombre(nombre:String)
executeQuery("select * from persona where nombre= %nombre")
next()
new()
r: ResultSet
getString("nombre"),...,: getString("telefono")
new Persona(nombre:String, direccion:String, telefono:String)
Pi: Persona
P1, P2, ... Pn()
getNombre()
getDireccion()
getTelefono()
Esta es la interfaz gráfica de usuario correspondiente al caso de uso:
A continuación presentamos una implementación INCOMPLETA en Java de dicho caso de uso
utilizando una arquitectura física en tres niveles.
package jun02;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.rmi.*;
public class IU_VP extends JFrame
{
JLabel jLabel1 = new JLabel();
JTextField jTextField1 = new JTextField();
JTextArea jTextArea1 = new JTextArea();
GestorPersonas g;
public IU_VP()
{
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void jbInit() throws Exception
{
jLabel1.setBounds(new Rectangle(17, 41, 130, 30));
this.getContentPane().setLayout(null);
this.setSize(new Dimension(400, 300));
this.setTitle("Pertsonen bilakatzaile / Buscador de Personas");
jLabel1.setRequestFocusEnabled(false);
jLabel1.setText("Izena / Nombre");
jTextField1.setBounds(new Rectangle(122, 40, 197, 33));
jTextField1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jTextField1_actionPerformed(e);
}
});
jTextArea1.setBounds(new Rectangle(45, 97, 261, 145));
this.getContentPane().add(jTextArea1, null);
this.getContentPane().add(jTextField1, null);
this.getContentPane().add(jLabel1, null);
}
public void setLogicaNegocio(GestorPersonas gp) {g=gp;}
void jTextField1_actionPerformed(ActionEvent e)
{
}
public static void main(String[] argc) {
IU_VP i = new IU_VP();
i.setVisible(true);
try{
System.setSecurityManager(new RMISecurityManager());
String url =
i.setLogicaNegocio((GestorPersonas)Naming.lookup(url));
}
catch (Exception ex) { }
}
}
package jun02;
import com.objectspace.jgl.Container;
public interface GestorPersonas
{
/** Método que busca personas con un determinado nombre
* @param n Nombre de la persona a buscar
* @return Container con los objetos de Persona que tienen dicho nombre
*/
Container buscarPorNombre(String n)
}
package jun02;
public class Persona
{
private String nombre;
private String direccion;
private String telefono;
public Persona(String n, String dir, String tel)
{ nombre=n; direccion=dir; telefono=tel; }
public String getNombre(){return nombre;}
public String getDireccion() {return direccion;}
public String getTelefono() {return telefono;}
}
package jun02;
import java.rmi.server.*;
import java.rmi.*;
import java.sql.*;
import java.util.*;
import com.objectspace.jgl.Container;
import com.objectspace.jgl.Array;
public class ImplGestorPersonas
{ PreparedStatement s;
Connection o;
public ImplGestorPersonas() throws RemoteException {
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
o=DriverManager.getConnection("jdbc:odbc:BDPers");
s=o.prepareStatement("select nombre, direccion, telefono"+
" from persona where nombre like ?"); }
catch (Exception ex){System.out.println("Error: "+ex.toString());}
}
public Container buscarPorNombre(String n) throws RemoteException
{
Array v=new Array();
}
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try { ImplGestorPersonas objetoServidor = new ImplGestorPersonas();
try { java.rmi.registry.LocateRegistry.createRegistry(1200); }
catch (Exception e) {System.out.println("Rmiregistry ya lanzado");}
Naming.rebind("//localhost:1200/gestorPersonas",
);
System.out.println("Lanzado el objeto servidor");
} catch (Exception e)
{System.out.println("Error al lanzar el servidor"+e.toString());}
}}
Se pide implementar el código correspondiente a la respuesta al evento “escribir un nombre en la
caja de texto de la interfaz gráfica de usuario”, la implementación del método buscarPor
Nombre y las llamadas a los métodos lookup y rebind de RMI. Además existen algunos
errores claros que hay que corregir.
SOLUCIÓN:
package jun02;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.rmi.*;
public class IU_VP extends JFrame
{
JLabel jLabel1 = new JLabel();
JTextField jTextField1 = new JTextField();
JTextArea jTextArea1 = new JTextArea();
GestorPersonas g;
public IU_VP()
{
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void jbInit() throws Exception
{
jLabel1.setBounds(new Rectangle(17, 41, 130, 30));
this.getContentPane().setLayout(null);
this.setSize(new Dimension(400, 300));
this.setTitle("Pertsonen bilakatzaile / Buscador de Personas");
jLabel1.setRequestFocusEnabled(false);
jLabel1.setText("Izena / Nombre");
jTextField1.setBounds(new Rectangle(122, 40, 197, 33));
jTextField1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
jTextField1_actionPerformed(e);
}
});
jTextArea1.setBounds(new Rectangle(45, 97, 261, 145));
this.getContentPane().add(jTextArea1, null);
this.getContentPane().add(jTextField1, null);
this.getContentPane().add(jLabel1, null);
}
public void setLogicaNegocio(GestorPersonas gp) {g=gp;}
void jTextField1_actionPerformed(ActionEvent e)
{
String nombre = jTextField1.getText();
try{
Enumeration en = g.buscarPorNombre(nombre).elements();
Persona p;
jTextArea1.setText("");
while (en.hasMoreElements()) {
p = (Persona)en.nextElement();
jTextArea1.append(p.getNombre()+"
"+p.getDireccion()+
"
"+p.getTelefono()+"\n");
}
}
catch(Exception ex)
{jTextArea1.append("Error en la conexión: "+ex.toString());}
}
public static void main(String[] argc) {
IU_VP i = new IU_VP();
i.setVisible(true);
try{
System.setSecurityManager(new RMISecurityManager());
String url = "rmi://localhost:1200/gestorPersonas";
i.setLogicaNegocio((GestorPersonas)Naming.lookup(url));
}
catch (Exception ex)
{i.jTextArea1.setText("Error al asignar la lógica del negocio\n");
i.jTextArea1.append(ex.toString());}
}
}
package jun02;
import com.objectspace.jgl.Container;
public interface GestorPersonas extends java.rmi.Remote
{
/** Método que busca personas con un determinado nombre
* @param n Nombre de la persona a buscar
* @return Container con los objetos de Persona que tienen dicho nombre
*/
Container buscarPorNombre(String n) throws java.rmi.RemoteException;
}
package jun02;
public class Persona implements java.io.Serializable
{
private String nombre;
private String direccion;
private String telefono;
public Persona(String n, String dir, String tel)
{
nombre=n;
direccion=dir;
telefono=tel;
}
public String getNombre(){return nombre;}
public String getDireccion() {return direccion;}
public String getTelefono() {return telefono;}
}
package jun02;
import java.rmi.server.*;
import java.rmi.*;
import java.sql.*;
import java.util.*;
import com.objectspace.jgl.Container;
import com.objectspace.jgl.Array;
public class ImplGestorPersonas extends UnicastRemoteObject
implements GestorPersonas
{
PreparedStatement s;
Connection o;
public ImplGestorPersonas() throws RemoteException
{
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
o=DriverManager.getConnection("jdbc:odbc:BDPers");
s=o.prepareStatement("select nombre, direccion, telefono"+
" from persona where nombre like ?");
}
catch (Exception ex){System.out.println("Error: "+ex.toString());}
}
public Container buscarPorNombre(String n) throws RemoteException
{
Array v=new Array();
try{
s.setString(1,"%"+n+"%");
ResultSet r=s.executeQuery();
while (r.next()) {
v.add(new Persona(r.getString("nombre"),
r.getString("direccion"),
r.getString("telefono")));}
} catch (Exception ex) {System.out.println("Error: "+ex.toString());}
return v;
}
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try {
ImplGestorPersonas objetoServidor = new ImplGestorPersonas();
try { java.rmi.registry.LocateRegistry.createRegistry(1200); }
catch (Exception e) {System.out.println("Rmiregistry ya lanzado");}
Naming.rebind("//localhost:1200/gestorPersonas",objetoServidor);
System.out.println("Lanzado el objeto servidor");
} catch (Exception e)
{System.out.println("Error al lanzar el servidor"+e.toString());}
}}
5.- (3,5 ptos.) (Tiempo estimado: 60’) Una operadora de telefonía ha puesto un nuevo servicio
disponible a sus clientes. El servicio “aviso de llamadas” consiste en enviar a los dispositivos pre establecidos por el cliente (correo electrónico, buscador, móvil o teléfono fijo ) la llegada de una
llamada de cualquiera de sus dispositivos. En el mensaje se indica el número del dispositivo a
partir del cual se ha realizado la llamada.
Los dispositivos se subscriben a otros dispositivos mediante el método subscribir(dispositivo) y se
pueden dar de baja mediante el método unsubscribir(dispositivo).
Suponiendo que el programa principal y su salida sea la siguiente:
public static void main(String[] args)
{
TelefonoFijo tfijo=new TelefonoFijo("943015052");
TelefonoMovil tmovil=new TelefonoMovil("Mi movil");
CorreoElectronico correo=new CorreoElectronico("iso@si.ehu.es");
Buscador bus=new Buscador("El busca de pepe");
tfijo.subscribir(tmovil);
tfijo.subscribir(bus);
tfijo.llamada(new TelefonoFijo("943015555"));
tfijo.unsubscribir(bus);
tfijo.llamada(correo);
correo.subscribir(tmovil);
correo.subscribir(tfijo);
correo.llamada(bus);
}
Mensaje
Mensaje
Mensaje
Mensaje
Mensaje
al
al
al
al
al
busca recibido en 943015052 enviado desde 943015555
móvil recibido en 943015052 enviado desde 943015555
móvil recibido en 943015052 enviado desde iso@si.ehu.es
fijo recibido en iso@si.ehu.es enviado desde El busca de pepe
móvil recibido en iso@si.ehu.es enviado desde El busca de pepe
SE PIDE:
1. Diagrama de clases para modelar la aplicación, con los métodos que estimes relevantes
2. Implementación de las clases del diseño.
3. Recientemente la operadora desea construir un nuevo módulo “almacenamiento de
llamadas”. Este módulo permite almacenar llamadas a través del método
insertLlamada(String numero) y devolver el conjunto de llamadas almacenadas a través del
método getLlamadas(). Diseña e implementa este módulo teniendo en cuenta que (1) NO
debes ofrecer detalles al cliente de este módulo, acerca de la implementación y (2) NO debes
utilizar ninguna librería de java en la signatura del método getLlamadas().
4. Modifica el diseño inicial para poder añadir la funcionalidad getLlamadasRecibidas() (p.ej.
correo.getLlamadasRecibidas()) a todos los dispositivos del sistema. Esta funcionalidad nos
devuelve todas llamadas redirigidas a un dispositivo.
5. Implementa los métodos necesarios para dar sopo rte al servicio del punto 4.
SOLUCIÓN:
1.-
Observable
Observer
m..n
(extends)
(implements)
Dispositivo
subscribir
unsubscribir
getUltimo
llamada
(extends)
TelefonoFijo
update()
(extends)
Buscador
update()
(extends)
TelefonoMovil
update()
(extends)
CorreoElectronico
update()
2.- El código que habría que implementar es el de las clases Dispositivo y
los dispositivos concretos. En este caso únicamente se muestra la
implementación de la clase TelefonoMovil
public abstract class Dispositivo extends Observable implements
Observer
{
String ultimoNumero;
String identificador;
public Dispositivo(String pIdent) {
identificador=pIdent;
}
public String getIdentificador() {return identificador;}
public void subscribir(Dispositivo pDisp) {
addObserver(pDisp);
}
public void unsubscribir(Dispositivo pDisp) {
deleteObserver(pDisp);
}
public String getUltimo(){
return ultimoNumero;
}
public void llamada(Dispositivo disp) {
ultimoNumero=disp.getIdentificador();
setChanged();
notifyObservers();
}
}
public class TelefonoMovil extends Dispositivo
{
public TelefonoMovil(String ident)
{
super(ident);
}
public void update(Observable t, Object o){
Dispositivo disp=(Dispositivo)t;
System.out.println("Mensaje al movil "+identificador+" recibido en
"+disp.getIdentificador()+" enviado desde "+disp.getUltimo());
}
}
3.-
Agregado
elements()
Enumeration
(use)
(implements)
MemoLlamada
sgetLlamadas()
añadirLlamada
hasMoreElements()
nextElement()
(implements)
EnumLlamds
(use)
hasMoreElements()
nextElement()
Se ha utilizado el patrón ITERATOR. Por lo tanto habrá que
implementar las clases MemoLlamadas y EnumLlamds.
public class MemoLlamadas
{
public Vector v;
public MemoLlamadas()
{
v=new Vector();
}
public void añadirLlamada(String s) {
v.add(s);
}
public Enumeration getLlamadas() {
return new MemoEnumerationLlamadas(this);
}
}
public class MemoEnumerationLlamadas implements Enumeration
{
MemoLlamadas memo;
int pos=0;
public MemoEnumerationLlamadas(MemoLlamadas m)
{
memo=m;
}
public boolean hasMoreElements() {
return (memo.v.size()>pos);
}
public Object nextElement() {
return memo.v.elementAt(pos++);
}
}
4.Observable
Observer
Agregado
m..n
elements()
Dispositivo
subscribir()
unsubscribir()
getUltimo()
llamada()
getLlamadasRecibidas
(use)
elements()
EnumLlamds
(use)
(extends)
(extends)
Buscador
(extends)
TelefonoMovil
update()
update()
update()
CorreoElectronico
update()
hasMoreElements()
nextElement()
(implements)
MemoLlamadas
(extends)
TelefonoFijo
(use)
(implements)
(implements)
(extends)
Enumeration
hasMoreElements()
nextElement()
5.- Los cambios que habría que realizar son los siguientes
public abstract class Dispositivo extends Observable implements Observer
{
protected MemoLlamadas memo;
public Enumeration getLlamadasRecibidas() {
return memo.elements();
}
public void addLlamada(String pNumero) {
memo.añadirLlamada(pNumero);
}
public class TelefonoMovil extends Dispositivo
{
public void update(Observable t, Object o){
Dispositivo disp=(Dispositivo)t;
System.out.println("Mensaje al movil "+identificador+" recibido en
"+disp.getIdentificador()+" enviado desde "+disp.getUltimo());
addLlamada(disp.getUltimo());
}
}
Descargar