Download 28 de MAYO de 2007

Document related concepts
no text concepts found
Transcript
INGENIERÍA DEL SOFTWARE. 4º ING. INFORMÁTICA (UPV/EHU)
28 de MAYO de 2007
NOMBRE:
GRUPO:
1ª PREGUNTA: ARQUITECTURAS EN 3 NIVELES) (2.5 ptos.) (Tiempo estimado: 45 minutos)
A continuación se presenta la implementación usando una arquitectura en 3 niveles físicos del caso
de uso PEDIR BILLETE que se ha utilizado durante este cuatrimestre (es exactamente el que
aparecía en la página web de la asignatura).
package ejsA3N;
import java.rmi.*;
public interface GestorBilletes extends Remote
{ public Billete getBillete(String nom) throws RemoteException; }
package ejsA3N;
import java.util.Date;
public class Billete implements java.io.Serializable
{ private int num; private String nomb; private Date fecha;
public Billete(int n,String nom){num=n; nomb=nom; fecha=new Date(); }
public int getNum(){return num;}
public String getNombre(){return nombre;}
public Date getFecha(){return fecha;} }
package ejsA3N;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.rmi.*;
public class PedirBillete extends JFrame {
JPanel jPanel1 = new JPanel(); JLabel jLabel1 = new JLabel();
JTextField jTextField1 = new JTextField();
JButton jButton1 = new JButton();
JTextArea jTextArea1 = new JTextArea();
GestorBilletes gestorBilletes; // Objeto con la lógica del negocio
public PedirBillete() {
super();
try {jbInit();} catch (Exception e) {e.printStackTrace();}}
private void jbInit() throws Exception {
this.getContentPane().setLayout(null);
this.setSize(new Dimension(400, 300));
jPanel1.setLayout(null);
jPanel1.setBounds(new Rectangle(0, 0, 392, 273));
jLabel1.setText("Nombre:");
jLabel1.setBounds(new Rectangle(54, 58, 64, 17));
jTextField1.setBounds(new Rectangle(124, 50, 163, 33));
jButton1.setText("Pedir Billete");
jButton1.setBounds(new Rectangle(103, 189, 156, 44));
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jButton1_actionPerformed(e);} });
jTextArea1.setBounds(new Rectangle(88, 94, 189, 76));
this.setTitle("Pedir Billetes");
this.getContentPane().add(jPanel1, null);
jPanel1.add(jLabel1, null); jPanel1.add(jTextField1, null);
jPanel1.add(jButton1, null); jPanel1.add(jTextArea1, null); }
public void setGestorBilletes(GestorBilletes g) { gestorBilletes=g; }
void jButton1_actionPerformed(ActionEvent e) {
try{int res =
gestorBilletes.getBillete(jTextField1.getText()).getNum();
if (res<0) jTextArea1.append("Error al asignar billete");
else jTextArea1.append("Asignado. \nReferencia: "+res+"\n");
} catch (Exception er) {System.out.println("Error: "+er.toString());
jTextArea1.append("Error al asignar billete");}}
public static void main (String []arg) {
PedirBillete b = new PedirBillete();
System.setSecurityManager(new RMISecurityManager());
String servicioRemoto = "rmi://localhost:1099/gestorBilletes”;
GestorBilletes objetoRemoto;
try{objetoRemoto = (GestorBilletes)Naming.lookup(servicioRemoto);
b.setGestorBilletes(objetoRemoto); }
catch (Exception e) {System.out.println("Error: "+e.toString());}
b.setVisible(true); }}
package ejsA3N;
import java.rmi.*;
import java.sql.*;
import java.io.*;
import java.rmi.server.UnicastRemoteObject;
import java.util.*;
public class ServidorGestorBilletesBD extends UnicastRemoteObject
implements GestorBilletes
{
private static Connection conexion;
private static Statement sentencia;
public ServidorGestorBilletesBD() throws RemoteException{
try {Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conexion=DriverManager.getConnection("jdbc:odbc:Billetes");
conexion.setAutoCommit(false);
sentencia=conexion.createStatement(); }
catch(Exception e){System.out.println("Error:"+e.toString());}}
public Billete getBillete(String nom)
throws RemoteException {
// Devuelve billete con nº billete, -1 si no hay, -2 problemas
String pregSQL = "SELECT NUMERO FROM BILLETES"+
" WHERE ESTADO=\'LIBRE\'";
try{ ResultSet rs = sentencia.executeQuery(pregSQL);
if (rs.next()) {
String num = rs.getString("NUMERO");
int act = sentencia.executeUpdate("UPDATE BILLETES"+
" SET ESTADO='OCUPADO', NOMBRE = '"+nom+
"' WHERE NUMERO="+num+" AND ESTADO='LIBRE'");
conexion.commit();
int n= Integer.parseInt(num);
if (act>0) return new Billete(n,nom); // N. bill asignado
return new Billete(-2,""); } // Otro ha OCUPADO billete
else return new Billete(-1,"");; } // No había libre
catch (SQLException e){System.out.println(e.toString());}
return new Billete(-2,""); } // Que prueben otra vez a llamar
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try { java.rmi.registry.LocateRegistry.createRegistry(numPuerto);
} catch (Exception e) {System.out.println(Rmiregistry exist");}
try { ServidorGestorBilletesBD objetoServidor =
new ServidorGestorBilletesBD();
String servicio="//localhost:1099/gestorBilletes";
Naming.rebind(servicio,objetoServidor);
} catch (Exception e){System.out.println(e.toString());}}}
Se trata de desarrollar un caso de uso similar al anterior llamado “PEDIR VARIOS BILLETES”
donde se puede pedir varios billetes a nombre de una persona. NOTA IMPORTANTE: si no se
pueden conseguir todos los billetes, entonces no se consigue ninguno: o todos o ninguno.
Se pide:
1) Diseñar en UML una solución para el caso de uso “PEDIR VARIOS BILLETES” que
utilice una arquitectura física en 3 niveles. Dicha solución debe ser extensible ante el
siguiente cambio en los requisitos: “se podrá pedir un número diferente de billetes a 1, 2 ó
3”. Por extensible se entenderá que “no habrá que modificar el nivel de presentación” en el
momento en que se decida aplicar el nuevo requisito.
2) Indicar TODOS LOS CAMBIOS que hay que hacer en la IMPLEMENTACIÓN con
respecto a la solución anterior del caso de uso “PEDIR BILLETES”. Cuando se trate de
un método nuevo hay que hacer la implementación completa del método.
Como ayuda incluimos parte de la implementación de la clase de presentación PedirNBilletes,
donde aparece solamente lo que es nuevo con respecto a la clase de presentación PedirBillete.
Nótese que en esta implementación sólo se permite pedir 1, 2 ó 3 billetes. Tampoco aparece la
implementación del evento “pulsar botón”, que claro está, se pide implementar.
...
public class PedirNBilletes extends JFrame {
...
JLabel jLabel2 = new JLabel();
JComboBox jComboBox1 = new JComboBox();
DefaultComboBoxModel comboBoxModel1 = new DefaultComboBoxModel();
...
private void jbInit() throws Exception {
...
jLabel2.setText("Num. billetes:");
jLabel2.setBounds(new Rectangle(55, 75, 115, 20));
jPanel1.add(jComboBox1, null);
jComboBox1.setBounds(new Rectangle(160, 75, 60, 20));
jComboBox1.setModel(comboBoxModel1);
this.setTitle("Pedir Varios Billetes");
comboBoxModel1.addElement("1");
comboBoxModel1.addElement("2");
comboBoxModel1.addElement("3"); }
void jButton1_actionPerformed(ActionEvent e) {// HAY QUE IMPLEMENTAR ESTO }
public static void main (String []arg) {...}
2ª PREGUNTA: PRUEBAS) (1,5 ptos.) (Tiempo estimado: 15 minutos) Diseñar el siguiente caso
de prueba para el caso de uso anterior e implementar un componente de prueba en JUNIT que lo
pruebe.
// OBJETIVO DEL CASO DE PRUEBA: comprobar que “si se pide un número de billetes mayor
a los disponibles en un momento dado, entonces no se obtiene ningún billete, incluso aunque
por lo menos hubiera uno disponible”.
Entrada:
Condiciones de entrada:
Salida:
NOTA: Si para el componente de prueba se usa alguna otra clase auxiliar, describirla usando
UML.
import junit.framework.*;
public class ComponentePruebaPedirNBilletes extends TestCase
{
public ComponentePruebaPedirNBilletes (String nombre)
{ super(nombre);
}
protected void setUp() {
}
protected void tearDown() {
}
// assertTrue(b) falla si y solo si b es false
public static Test suite() {
return new TestSuite(ComponentePruebaPedirNBilletes.class);
}
public static void main(String args[]) {
junit.textui.TestRunner.run(suite());
}
}
3ª PREGUNTA: JGL) (2 ptos.) (Tiempo estimado: 40 minutos) La clase función unaria de JGL
Prime devuelve como resultado si un número es primo. Basándote en esta clase, implementa la
función PrimoPositivoMasCercano que dado un número, devuelve su número primo positivo
más cercano.
2. La clase función UnaryCompose en JGL es una clase que tiene como atributos 2 objetos
UnaryFunction uf1 y uf2, y para un elemento x de entrada devuelve como resultado uf1(uf2(x)).
¿Cómo implementarías esta clase?
3. Realizar un programa que dado un Container de elementos enteros, devuelva en otro Container,
el resultado de transformar cada elemento del contenedor inicial por su primo positivo más
cercano, utilizando las clases definidas en los apartados 1 y 2.
Ejemplo: (-6,4,3,-9) > (7,5,3,11)
Nota:
El
algoritmo
Trasforming.transform(Container
c1<T>,
Container
c2<R>,
UnaryFunction<T,R> uf), aplica la funcion uf a cada elementos del container c1, dejando el
resultado en el Container c2.
4ª PREGUNTA: EJB) (2 ptos.) (Tiempo estimado: 30 minutos) Una Liga de Fútbol, para la
gestión de los partidos de una jornada ha desarrollado un componente que permite, crear partidos,
anotar un gol por parte de un equipo, consultar el marcador, comprobar si el partido está en juego
o no, y finalmente dar por terminado un partido. Cuando finaliza el partido, el componente
notifica al componente Gestor de Quinielas la información del partido jugado, es decir, los equipos
y el resultado (1X2).
Partido
GestorQuinielas
void anotarResultado (String eq1,
String eq2, String resultado)
Se pide implementar el componente Partido, que apoyándose en el componente GestorQuinielas,
permita:
1- Crear objetos Partido
2. Ejecutar las operaciones descritas en el párrafo anterior.
3. De qué tipo son los componentes Partido y GestorQuinielas?. Justifica brevemente tu respuesta
5ª PREGUNTA: PATRONES DE DISEÑO) (2 ptos.) (Tiempo estimado: 50 minutos) Queremos
construir una aplicación que gestione los goles que se vayan produciendo en una jornada de un
campeonato de fútbol. Una primera aproximación al modelo de dominio a utilizar para
implementar la aplicación será el reflejado en el Diagrama de Clases que se adjunta:
Partido
Jornada
1
*
MedioComunicacion
-identificador : String
-idEquipo1 : String
-idEquipo2 : String
+gol()
1
goles
*
PrensaDigital
Gol
-idEquipo : String
-idJugador : String
-minuto : String
+actualizarTabla()
Radio
+cantarGol()
Television
+actualizarTXT()
Siempre que se produzca un gol en la jornada el objeto Partido recibe un método gol() con la
siguiente información:
gol(String idEquipo, String idJugador, String minuto)
Si un medio de comunicación(PrensaDigital, Radio o Televisión) quiere recibir información
actualizada de los goles que se produzcan en la jornada debe suscribirse al partido o partidos de los
cuales quiere recibir información. La aplicación informará puntualmente a cada medio suscrito de
los goles que se produzcan en el campeonato. La aplicación deberá permitir que un medio de
comunicación pueda suscribirse invocando un solo método a todos los partidos de la jornada.
Se pide:
Diseñar un modelo de clases que permita recoger las funcionalidades descritas, indicando
claramente cuál(es) son los patrón(es) utilizados.
Implementar los las clases que estimes oportunas.