Gestión de dependencias con Maven Comunicación cliente-servidor con Sockets Servidor HTTP simple Consumo de APIs con HttpClient Ejercicio de Despedida: App Swing + PokeAPI
Maven es una herramienta de gestión de proyectos basada en el concepto de POM (Project Object Model).
<!-- Estructura básica de un archivo pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ejemplo</groupId>
<artifactId>mi-proyecto</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- Dependencias del proyecto -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>
<dependencies>
<!-- Para trabajar con JSON -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<!-- Para realizar peticiones HTTP -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<!-- Para pruebas unitarias -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.3</version>
<scope>test</scope>
</dependency>
</dependencies>
// Ejemplo de uso de la librería Gson para trabajar con JSON
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class EjemploGson {
public static void main(String[] args) {
// Crear un objeto para serializar
Persona persona = new Persona("Juan", "Pérez", 30);
// Convertir objeto a JSON
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(persona);
System.out.println("Objeto a JSON:");
System.out.println(json);
// Convertir JSON a objeto
String jsonInput = "{\"nombre\":\"María\",\"apellido\":\"López\",\"edad\":25}";
Persona personaDeJson = gson.fromJson(jsonInput, Persona.class);
System.out.println("\nJSON a Objeto:");
System.out.println("Nombre: " + personaDeJson.getNombre());
System.out.println("Apellido: " + personaDeJson.getApellido());
System.out.println("Edad: " + personaDeJson.getEdad());
}
}
class Persona {
private String nombre;
private String apellido;
private int edad;
public Persona(String nombre, String apellido, int edad) {
this.nombre = nombre;
this.apellido = apellido;
this.edad = edad;
}
// Getters y setters
public String getNombre() { return nombre; }
public String getApellido() { return apellido; }
public int getEdad() { return edad; }
}
Los sockets proporcionan un mecanismo para la comunicación entre procesos a través de la red.
// Esta interfaz define los servicios que ofrecerá nuestro servidor
public interface ServicioRemoto {
String saludar(String nombre);
int sumar(int a, int b);
void enviarMensaje(String remitente, String mensaje);
}
import java.io.*;
import java.net.*;
public class Servidor implements ServicioRemoto {
private static final int PUERTO = 5000;
public static void main(String[] args) {
new Servidor().iniciar();
}
public void iniciar() {
try (ServerSocket serverSocket = new ServerSocket(PUERTO)) {
System.out.println("Servidor iniciado en puerto " + PUERTO);
while (true) {
Socket clienteSocket = serverSocket.accept();
System.out.println("Cliente conectado: " + clienteSocket.getInetAddress());
// Crear hilo para manejar cliente
Thread clienteHandler = new Thread(new ManejadorCliente(clienteSocket, this));
clienteHandler.start();
}
} catch (IOException e) {
System.out.println("Error en el servidor: " + e.getMessage());
}
}
@Override
public String saludar(String nombre) {
return "¡Hola, " + nombre + "!";
}
@Override
public int sumar(int a, int b) {
return a + b;
}
@Override
public void enviarMensaje(String remitente, String mensaje) {
System.out.println("[" + remitente + "]: " + mensaje);
}
}
class ManejadorCliente implements Runnable {
private Socket clienteSocket;
private ServicioRemoto servicio;
public ManejadorCliente(Socket socket, ServicioRemoto servicio) {
this.clienteSocket = socket;
this.servicio = servicio;
}
@Override
public void run() {
try (
BufferedReader entrada = new BufferedReader(
new InputStreamReader(clienteSocket.getInputStream()));
PrintWriter salida = new PrintWriter(
clienteSocket.getOutputStream(), true)
) {
String lineaEntrada;
while ((lineaEntrada = entrada.readLine()) != null) {
// Procesar comandos del cliente
if (lineaEntrada.startsWith("SALUDAR:")) {
String nombre = lineaEntrada.substring(8);
salida.println(servicio.saludar(nombre));
} else if (lineaEntrada.startsWith("SUMAR:")) {
String[] numeros = lineaEntrada.substring(6).split(",");
int a = Integer.parseInt(numeros[0]);
int b = Integer.parseInt(numeros[1]);
salida.println(servicio.sumar(a, b));
} else if (lineaEntrada.startsWith("MENSAJE:")) {
String[] partes = lineaEntrada.substring(8).split(":");
servicio.enviarMensaje(partes[0], partes[1]);
salida.println("Mensaje recibido");
} else if (lineaEntrada.equals("SALIR")) {
break;
}
}
} catch (IOException e) {
System.out.println("Error con cliente: " + e.getMessage());
} finally {
try {
clienteSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Cliente {
private static final String HOST = "localhost";
private static final int PUERTO = 5000;
private Socket socket;
private PrintWriter salida;
private BufferedReader entrada;
private String nombreUsuario;
public static void main(String[] args) {
new Cliente().iniciar();
}
public void iniciar() {
try {
// Conectar al servidor
socket = new Socket(HOST, PUERTO);
salida = new PrintWriter(socket.getOutputStream(), true);
entrada = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Scanner scanner = new Scanner(System.in);
// Solicitar nombre de usuario
System.out.print("Ingrese su nombre de usuario: ");
nombreUsuario = scanner.nextLine();
// Iniciar hilo para recibir mensajes del servidor
Thread hiloLectura = new Thread(this::leerMensajes);
hiloLectura.start();
// Procesar comandos del usuario
boolean ejecutando = true;
while (ejecutando) {
System.out.println("\nComandos disponibles:");
System.out.println("1. Saludar");
System.out.println("2. Sumar dos números");
System.out.println("3. Enviar mensaje");
System.out.println("4. Salir");
System.out.print("Ingrese una opción: ");
int opcion = Integer.parseInt(scanner.nextLine());
switch (opcion) {
case 1:
System.out.print("Ingrese nombre para saludar: ");
String nombre = scanner.nextLine();
salida.println("SALUDAR:" + nombre);
break;
case 2:
System.out.print("Ingrese primer número: ");
int a = Integer.parseInt(scanner.nextLine());
System.out.print("Ingrese segundo número: ");
int b = Integer.parseInt(scanner.nextLine());
salida.println("SUMAR:" + a + "," + b);
break;
case 3:
System.out.print("Mensaje: ");
String mensaje = scanner.nextLine();
salida.println("MENSAJE:" + nombreUsuario + ":" + mensaje);
break;
case 4:
ejecutando = false;
salida.println("SALIR");
break;
default:
System.out.println("Opción no válida");
}
}
// Cerrar recursos
socket.close();
scanner.close();
} catch (IOException e) {
System.out.println("Error en el cliente: " + e.getMessage());
}
}
private void leerMensajes() {
try {
String mensajeServidor;
while ((mensajeServidor = entrada.readLine()) != null) {
System.out.println("\nRespuesta del servidor: " + mensajeServidor);
System.out.print("Ingrese una opción: ");
}
} catch (IOException e) {
if (!socket.isClosed()) {
System.out.println("Error leyendo del servidor: " + e.getMessage());
}
}
}
}
Un servidor que responde peticiones HTTP básicas visible desde un navegador.
import java.io.*;
import java.net.*;
public class ServidorHTTP {
private static final int PUERTO = 8080;
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(PUERTO)) {
System.out.println("Servidor HTTP iniciado en puerto " + PUERTO);
System.out.println("Abra su navegador y vaya a http://localhost:" + PUERTO);
while (true) {
Socket clienteSocket = serverSocket.accept();
Thread hiloCliente = new Thread(() -> manejarConexion(clienteSocket));
hiloCliente.start();
}
} catch (IOException e) {
System.out.println("Error en el servidor: " + e.getMessage());
}
}
private static void manejarConexion(Socket clienteSocket) {
try (
BufferedReader entrada = new BufferedReader(
new InputStreamReader(clienteSocket.getInputStream()));
PrintWriter salida = new PrintWriter(
clienteSocket.getOutputStream(), true)
) {
// Leer la solicitud
String lineaEntrada;
while ((lineaEntrada = entrada.readLine()) != null) {
if (lineaEntrada.isEmpty()) {
break; // La solicitud HTTP termina con una línea vacía
}
System.out.println(lineaEntrada);
}
// Enviar respuesta
String html = "<!DOCTYPE html>" +
"<html>" +
"<head>" +
" <title>Servidor HTTP Simple</title>" +
" <style>" +
" body { font-family: Arial, sans-serif; margin: 40px; }" +
" h1 { color: #2c3e50; }" +
" .container { background-color: #ecf0f1; padding: 20px; " +
" border-radius: 5px; max-width: 600px; }" +
" .highlight { color: #e74c3c; font-weight: bold; }" +
" </style>" +
"</head>" +
"<body>" +
" <div class='container'>" +
" <h1>¡Hola desde mi Servidor HTTP!</h1>" +
" <p>Este es un servidor HTTP simple implementado en Java.</p>" +
" <p>Hora actual: <span class='highlight'>" +
java.time.LocalDateTime.now() + "</span></p>" +
" </div>" +
"</body>" +
"</html>";
// Cabeceras HTTP
salida.println("HTTP/1.1 200 OK");
salida.println("Content-Type: text/html; charset=UTF-8");
salida.println("Content-Length: " + html.length());
salida.println(); // Línea vacía entre cabeceras y cuerpo
salida.println(html);
} catch (IOException e) {
System.out.println("Error con cliente: " + e.getMessage());
} finally {
try {
clienteSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Usando Apache HttpClient para hacer peticiones a APIs externas.
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class ConsumirAPI {
public static void main(String[] args) {
// Crear el cliente HTTP
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// Definir la URL de la API
String url = "https://pokeapi.co/api/v2/pokemon/pikachu";
// Crear la solicitud GET
HttpGet request = new HttpGet(url);
// Ejecutar la solicitud
try (CloseableHttpResponse response = httpClient.execute(request)) {
// Obtener el código de estado
int statusCode = response.getStatusLine().getStatusCode();
System.out.println("Código de estado: " + statusCode);
// Obtener el cuerpo de la respuesta
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity);
// Parsear el JSON con Gson
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(result, JsonObject.class);
// Extraer información relevante
String nombre = jsonObject.get("name").getAsString();
int altura = jsonObject.get("height").getAsInt();
int peso = jsonObject.get("weight").getAsInt();
int id = jsonObject.get("id").getAsInt();
// Mostrar la información
System.out.println("Información del Pokémon:");
System.out.println("ID: " + id);
System.out.println("Nombre: " + nombre);
System.out.println("Altura: " + altura/10.0 + " m");
System.out.println("Peso: " + peso/10.0 + " kg");
// Obtener tipos
System.out.println("Tipos:");
jsonObject.getAsJsonArray("types").forEach(element -> {
String tipo = element.getAsJsonObject()
.getAsJsonObject("type")
.get("name").getAsString();
System.out.println("- " + tipo);
});
// Obtener URL de la imagen frontal
String urlImagen = jsonObject.getAsJsonObject("sprites")
.get("front_default").getAsString();
System.out.println("URL de la imagen: " + urlImagen);
}
}
} catch (Exception e) {
System.out.println("Error al consumir la API: " + e.getMessage());
e.printStackTrace();
}
}
}
// Clase POJO para mapear los datos de un Pokémon
public class Pokemon {
private int id;
private String name;
private int height;
private int weight;
private List<PokemonType> types;
private Sprites sprites;
private List<Stat> stats;
// Getters (se omiten setters si se usa solo para deserialización)
public int getId() { return id; }
public String getName() { return name; }
public int getHeight() { return height; }
public int getWeight() { return weight; }
public List<PokemonType> getTypes() { return types; }
public Sprites getSprites() { return sprites; }
public List<Stat> getStats() { return stats; }
// Clases internas para la estructura anidada
public static class PokemonType {
private int slot;
private Type type;
public int getSlot() { return slot; }
public Type getType() { return type; }
}
public static class Type {
private String name;
private String url;
public String getName() { return name; }
public String getUrl() { return url; }
}
public static class Sprites {
private String front_default;
private String back_default;
public String getFrontDefault() { return front_default; }
public String getBackDefault() { return back_default; }
}
public static class Stat {
private int base_stat;
private int effort;
private StatInfo stat;
public int getBaseStat() { return base_stat; }
public int getEffort() { return effort; }
public StatInfo getStat() { return stat; }
}
public static class StatInfo {
private String name;
private String url;
public String getName() { return name; }
public String getUrl() { return url; }
}
@Override
public String toString() {
return "Pokemon{" +
"id=" + id +
", name='" + name + '\'' +
", height=" + height +
", weight=" + weight +
'}';
}
}
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.google.gson.Gson;
import java.io.IOException;
public class PokemonService {
private static final String API_BASE_URL = "https://pokeapi.co/api/v2/";
private final CloseableHttpClient httpClient;
private final Gson gson;
public PokemonService() {
this.httpClient = HttpClients.createDefault();
this.gson = new Gson();
}
public Pokemon getPokemonByName(String name) throws IOException {
String url = API_BASE_URL + "pokemon/" + name.toLowerCase();
return executeRequest(url, Pokemon.class);
}
public Pokemon getPokemonById(int id) throws IOException {
String url = API_BASE_URL + "pokemon/" + id;
return executeRequest(url, Pokemon.class);
}
private <T> T executeRequest(String url, Class<T> responseType) throws IOException {
HttpGet request = new HttpGet(url);
try (CloseableHttpResponse response = httpClient.execute(request)) {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode >= 200 && statusCode < 300) {
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity);
return gson.fromJson(result, responseType);
}
}
throw new IOException("Request failed with status code: " + statusCode);
}
}
// Es importante cerrar el cliente HTTP cuando ya no se necesita
public void close() throws IOException {
if (httpClient != null) {
httpClient.close();
}
}
// Ejemplo de uso
public static void main(String[] args) {
try (PokemonService service = new PokemonService()) {
Pokemon pokemon = service.getPokemonByName("charizard");
System.out.println(pokemon);
System.out.println("Altura: " + pokemon.getHeight()/10.0 + " m");
System.out.println("Peso: " + pokemon.getWeight()/10.0 + " kg");
System.out.println("Tipos:");
pokemon.getTypes().forEach(type -> {
System.out.println("- " + type.getType().getName());
});
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
Vamos a desarrollar una aplicación de escritorio simple que nos permita buscar y mostrar información de Pokémon.
src/
├── main/
│ ├── java/
│ │ ├── com/
│ │ │ └── ejemplo/
│ │ │ ├── pokeapp/
│ │ │ │ ├── model/
│ │ │ │ │ └── Pokemon.java (y clases relacionadas)
│ │ │ │ ├── service/
│ │ │ │ │ └── PokemonService.java
│ │ │ │ └── ui/
│ │ │ │ └── PokemonApp.java
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ejemplo</groupId>
<artifactId>poke-app</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- Para realizar peticiones HTTP -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<!-- Para trabajar con JSON -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
package com.ejemplo.pokeapp.model;
import java.util.List;
public class Pokemon {
private int id;
private String name;
private int height;
private int weight;
private List<PokemonType> types;
private Sprites sprites;
private List<Stat> stats;
// Getters
public int getId() { return id; }
public String getName() { return name; }
public int getHeight() { return height; }
public int getWeight() { return weight; }
public List<PokemonType> getTypes() { return types; }
public Sprites getSprites() { return sprites; }
public List<Stat> getStats() { return stats; }
// Clases internas para la estructura anidada
public static class PokemonType {
private int slot;
private Type type;
public int getSlot() { return slot; }
public Type getType() { return type; }
}
public static class Type {
private String name;
private String url;
public String getName() { return name; }
public String getUrl() { return url; }
}
public static class Sprites {
private String front_default;
private String back_default;
public String getFrontDefault() { return front_default; }
public String getBackDefault() { return back_default; }
}
public static class Stat {
private int base_stat;
private int effort;
private StatInfo stat;
public int getBaseStat() { return base_stat; }
public int getEffort() { return effort; }
public StatInfo getStat() { return stat; }
}
public static class StatInfo {
private String name;
private String url;
public String getName() { return name; }
public String getUrl() { return url; }
}
}
package com.ejemplo.pokeapp.service;
import com.ejemplo.pokeapp.model.Pokemon;
import com.google.gson.Gson;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
public class PokemonService implements AutoCloseable {
private static final String API_BASE_URL = "https://pokeapi.co/api/v2/";
private final CloseableHttpClient httpClient;
private final Gson gson;
public PokemonService() {
this.httpClient = HttpClients.createDefault();
this.gson = new Gson();
}
public Pokemon getPokemonByName(String name) throws IOException {
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("El nombre no puede estar vacío");
}
String url = API_BASE_URL + "pokemon/" + name.toLowerCase().trim();
return executeRequest(url, Pokemon.class);
}
public Pokemon getPokemonById(int id) throws IOException {
if (id <= 0) {
throw new IllegalArgumentException("El ID debe ser un número positivo");
}
String url = API_BASE_URL + "pokemon/" + id;
return executeRequest(url, Pokemon.class);
}
private <T> T executeRequest(String url, Class<T> responseType) throws IOException {
HttpGet request = new HttpGet(url);
try (CloseableHttpResponse response = httpClient.execute(request)) {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode >= 200 && statusCode < 300) {
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity);
return gson.fromJson(result, responseType);
}
}
throw new IOException("La petición falló con código: " + statusCode);
}
}
@Override
public void close() throws Exception {
if (httpClient != null) {
httpClient.close();
}
}
}
package com.ejemplo.pokeapp.ui;
import com.ejemplo.pokeapp.model.Pokemon;
import com.ejemplo.pokeapp.service.PokemonService;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.URL;
import java.util.stream.Collectors;
public class PokemonApp extends JFrame {
private final PokemonService pokemonService;
private JTextField searchField;
private JButton searchButton;
private JLabel nameLabel;
private JLabel idLabel;
private JLabel heightLabel;
private JLabel weightLabel;
private JLabel typesLabel;
private JLabel imageLabel;
private JPanel statsPanel;
public PokemonApp() {
pokemonService = new PokemonService();
setupUI();
// Cerrar recursos al cerrar la ventana
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
try {
pokemonService.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
}
private void setupUI() {
setTitle("PokeApp");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 400);
setLocationRelativeTo(null);
// Panel principal con BorderLayout
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// Panel de búsqueda en la parte superior
JPanel searchPanel = new JPanel(new BorderLayout(5, 0));
searchField = new JTextField();
searchButton = new JButton("Buscar");
searchPanel.add(new JLabel("Nombre o ID: "), BorderLayout.WEST);
searchPanel.add(searchField, BorderLayout.CENTER);
searchPanel.add(searchButton, BorderLayout.EAST);
// Panel de información a la izquierda
JPanel infoPanel = new JPanel(new GridLayout(5, 1, 5, 5));
nameLabel = new JLabel("Nombre: ");
idLabel = new JLabel("ID: ");
heightLabel = new JLabel("Altura: ");
weightLabel = new JLabel("Peso: ");
typesLabel = new JLabel("Tipos: ");
infoPanel.add(nameLabel);
infoPanel.add(idLabel);
infoPanel.add(heightLabel);
infoPanel.add(weightLabel);
infoPanel.add(typesLabel);
// Panel para la imagen a la derecha
JPanel imagePanel = new JPanel(new BorderLayout());
imageLabel = new JLabel("", SwingConstants.CENTER);
imagePanel.add(imageLabel, BorderLayout.CENTER);
// Panel para las estadísticas abajo
statsPanel = new JPanel(new GridLayout(1, 6, 5, 0));
statsPanel.setBorder(BorderFactory.createTitledBorder("Estadísticas"));
// Añadir componentes al panel principal
mainPanel.add(searchPanel, BorderLayout.NORTH);
mainPanel.add(infoPanel, BorderLayout.WEST);
mainPanel.add(imagePanel, BorderLayout.CENTER);
mainPanel.add(statsPanel, BorderLayout.SOUTH);
// Configurar acción de búsqueda
searchButton.addActionListener(this::searchPokemon);
searchField.addActionListener(this::searchPokemon); // Buscar al presionar Enter
// Añadir panel principal al frame
add(mainPanel);
}
private void searchPokemon(ActionEvent e) {
String query = searchField.getText().trim();
if (query.isEmpty()) {
JOptionPane.showMessageDialog(this,
"Por favor ingrese un nombre o ID de Pokémon",
"Campo vacío", JOptionPane.WARNING_MESSAGE);
return;
}
try {
Pokemon pokemon;
// Determinar si la búsqueda es por ID o por nombre
if (query.matches("\\d+")) {
int id = Integer.parseInt(query);
pokemon = pokemonService.getPokemonById(id);
} else {
pokemon = pokemonService.getPokemonByName(query);
}
displayPokemon(pokemon);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this,
"Error al buscar el Pokémon: " + ex.getMessage(),
"Error", JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
}
}
private void displayPokemon(Pokemon pokemon) {
// Actualizar etiquetas de información
nameLabel.setText("Nombre: " + capitalizarPrimeraLetra(pokemon.getName()));
idLabel.setText("ID: " + pokemon.getId());
heightLabel.setText("Altura: " + (pokemon.getHeight() / 10.0) + " m");
weightLabel.setText("Peso: " + (pokemon.getWeight() / 10.0) + " kg");
// Mostrar tipos
String tipos = pokemon.getTypes().stream()
.map(type -> capitalizarPrimeraLetra(type.getType().getName()))
.collect(Collectors.joining(", "));
typesLabel.setText("Tipos: " + tipos);
// Mostrar imagen
try {
String imageUrl = pokemon.getSprites().getFrontDefault();
if (imageUrl != null && !imageUrl.isEmpty()) {
ImageIcon icon = new ImageIcon(new URL(imageUrl));
imageLabel.setIcon(icon);
} else {
imageLabel.setIcon(null);
imageLabel.setText("Imagen no disponible");
}
} catch (Exception e) {
imageLabel.setIcon(null);
imageLabel.setText("Error al cargar imagen");
e.printStackTrace();
}
// Actualizar panel de estadísticas
statsPanel.removeAll();
if (pokemon.getStats() != null) {
for (Pokemon.Stat stat : pokemon.getStats()) {
String statName = stat.getStat().getName();
int value = stat.getBaseStat();
// Simplificar nombres de estadísticas
String displayName = switch (statName) {
case "hp" -> "HP";
case "attack" -> "ATK";
case "defense" -> "DEF";
case "special-attack" -> "SP.ATK";
case "special-defense" -> "SP.DEF";
case "speed" -> "SPD";
default -> statName;
};
JPanel statPanel = new JPanel(new BorderLayout(0, 5));
JLabel nameLabel = new JLabel(displayName, SwingConstants.CENTER);
JLabel valueLabel = new JLabel(String.valueOf(value), SwingConstants.CENTER);
JProgressBar bar = new JProgressBar(0, 255);
bar.setValue(value);
bar.setStringPainted(true);
bar.setString(String.valueOf(value));
statPanel.add(nameLabel, BorderLayout.NORTH);
statPanel.add(bar, BorderLayout.CENTER);
statsPanel.add(statPanel);
}
}
// Repintar
statsPanel.revalidate();
statsPanel.repaint();
}
private String capitalizarPrimeraLetra(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
PokemonApp app = new PokemonApp();
app.setVisible(true);
});
}
}
La aplicación final permite: