Skip to content

Commit 897b661

Browse files
committed
Mejora el ejemplo de YAML con Jackson
1 parent e0eabf0 commit 897b661

File tree

3 files changed

+82
-56
lines changed

3 files changed

+82
-56
lines changed

source/01.archivos/01.gestion.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,8 @@ podemos hacer construcciones como esta:
255255

256256
.. _file-arc-pro:
257257

258-
Archivos del proyecto
259-
---------------------
258+
Archivos de recursos
259+
--------------------
260260
Es común que, cuando desarrollamos una aplicación, tengamos que hacer referencia
261261
a archivos que hemos incluido dentro de ella. Un error de principiante es hacer
262262
lo siguiente:
@@ -300,11 +300,11 @@ invocar el método.
300300
.. caution:: En los proyectos de *Java* suele existir un directorio
301301
:file:`resources` para almacenar archivos con datos. El contenido de este
302302
directorio acaba en la aplicación en la raíz del *classpath*. Por tanto, el
303-
archivo de imagen que hemos puesto de ejemplo, podríamos hacerlo incluido en
304-
este subdirectorio del proyecto. Ahora bien, con :ref:`Maven` la copia a
303+
archivo de imagen que hemos puesto de ejemplo, deberíamos haberlo incluido
304+
en este subdirectorio del proyecto. Ahora bien, con :ref:`Maven` la copia a
305305
*classpath* no es automática y hay que declararla en :file:`pom.xml`. Vea un
306-
ejemplo de :ref:`cómo añadir archivos con propiedades <add-resources>` en uno
307-
de los apéndices.
306+
ejemplo de :ref:`cómo añadir archivos de recursos <add-resources>` en
307+
uno de los apéndices.
308308

309309
.. _file.files:
310310

source/02.formatos/03.yaml.rst

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,16 @@ y modificar la forma en que definimos el mapeador:
1313
.. code-block:: java
1414
1515
YAMLFactory factory = YAMLFactory.builder()
16+
// Podemos habilitar o deshabilitar características del formato.
1617
.build();
1718
18-
MapperBuilder<?, ?> builder = YAMLMapper.builder(factory);
19+
MapperBuilder<?, ?> builder = YAMLMapper.builder(factory)
20+
// Podemos habilitar o deshabilitar características generales.
21+
// Añadir módulos
22+
// Hacer mixIn
23+
;
1924
20-
ObjectMapper mapper = builder.build();
25+
ObjectMapper mapper = builder.build(); // Mapeador inmutable.
2126
2227
.. |YAML| replace:: :abbr:`YAML (YAML Ain't Markup Language)`
2328
.. |JSON| replace:: :abbr:`JSON (JavaScript Object Notation)`

source/03.xml/01.jaxp.rst

Lines changed: 69 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -183,40 +183,55 @@ En primer lugar, si queremos que la validación se lleve a cabo debemos añadir:
183183
factory.setValidating(true);
184184
185185
Otro aspecto importante es el de la manipulación de la validación, que se lleva
186-
cabo definiendo un \"*resolutor de entidades*\".
186+
a cabo definiendo un *resolutor de entidades*.
187187

188188
.. code-block:: java
189-
:emphasize-lines: 1,13,14,27
190-
191-
builder.setEntityResolver(new EntityResolver2() {
192-
@Override
193-
public InputSource getExternalSubset(String name, String baseURI) {
194-
return null;
195-
}
196-
197-
@Override
198-
public InputSource resolveEntity(String publicID, String systemID) throws SAXException, IOException {
199-
return resolveEntity(null, publicID, null, systemID);
200-
}
201-
202-
@Override
203-
public InputSource resolveEntity(String name, String publicID, String baseURI, String systemID)
204-
throws SAXException, IOException {
205-
if(systemID == null) return null;
206-
207-
try {
208-
if(!new URI(systemID).isAbsolute()) {
209-
// Se supone que "ruta" ya se definió como Path.
210-
systemID = ruta.getParent().resolve(systemID).toString();
211-
}
212-
}
213-
catch(URISyntaxException err) {
214-
return null;
215-
}
216-
217-
return new InputSource(systemID);
218-
}
219-
});
189+
:emphasize-lines: 1,3,4,9,10,15,16
190+
191+
builder.setEntityResolver(new EntityResolver2() {
192+
@Override
193+
public InputSource getExternalSubset(String name, String baseURI)
194+
throws SAXException, IOException {
195+
return null;
196+
}
197+
198+
@Override
199+
public InputSource resolveEntity(String publicId, String systemId)
200+
throws SAXException, IOException {
201+
return resolveEntity(null, publicId, null, systemId);
202+
}
203+
204+
@Override
205+
public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId)
206+
throws SAXException, IOException {
207+
208+
if (systemId == null) return null;
209+
210+
try {
211+
systemId = resolvePath(baseURI, systemId);
212+
} catch(URISyntaxException e) {
213+
return null;
214+
}
215+
216+
return new InputSource(systemId);
217+
}
218+
219+
private String resolvePath(String base, String path) throws URISyntaxException {
220+
if(new URI(path).isAbsolute()) return path;
221+
if(base == null) throw new IllegalArgumentException("No puede calcularse una ruta relativa si la base es nula.");
222+
223+
if(base.contains("!")) {
224+
// Nos quedamos con la parte del path dentro del jar
225+
Path basePath = Path.of(base.substring(base.indexOf("!") + 1));
226+
// Resolvemos el path relativo y devolvemos el recurso.
227+
URL resource = getClass().getResource(basePath.resolveSibling(path).toString());
228+
return resource != null ? resource.toString() : null;
229+
}
230+
231+
return new URI(base).resolve(path).toString();
232+
}
233+
234+
});
220235
221236
Debemos fijarnos en el último método. Cuando devuelve `null`, es como, si no
222237
hubiéramos definido nada, y el procesador obrará como lo hace habitualmente para
@@ -227,25 +242,27 @@ original.
227242

228243
.. admonition:: Advertencia
229244

230-
El código incluye una variable ``ruta``, que es un objeto |Path| que
231-
contiene la ruta del archivo |XML| en consonancia con :ref:`el ejemplo
232-
ilustrativo que escribimos sobre lectura <jaxp-read>`.
245+
Este código da por hecho que se conoce la ruta del |XML| (``baseURI``). Esto,
246+
sin embargo, puede ser cierto o no. Todo este procesamiento lo desencadena
247+
:code:`builder.parse()`, el cual permite proporcionar los datos de distinto
248+
modo. Puede pasarse un |String| o un |File| en cuyo caso
249+
sí se sabrá ``baseURI``. En cambio, si se pasa un |InputStream| (que es
250+
*precisamente la forma en la que hemos ilustrado el uso*) no hay modo de
251+
conocer su valor y, en consencuencia, será ``null``. Eso sí, en este último
252+
caso, se admite un segundo argumento con una cadena que defina ``baseURI``.
233253

234-
Si en cambio, ``ruta`` fuera una objeto :java-net:`URI <URI>` podríamos obtener la cadena
235-
con la ruta del |DTD| de este otro modo:
236-
237-
.. code-block:: java
254+
¿Qué hace exactamente el código que hemos propuesto? En principio, si
255+
no hay definido ningun |DTD|, no hace nada. En cambio, si hay definido uno,
256+
comprueba si el |DTD| se proporciona con ruta absoluta. Si es así, respeta el
257+
valor y la validación se hará con el valor expresado en el archivo. En cambio,
258+
si la ruta es relativa, hace una distinción:
238259

239-
systemID = ruta.resolve(systemID).toString();
260+
* Si ``baseURI`` contiene el carácter ``!`` se ha pasado como |XML| un
261+
:ref:`archivo de recursos <file-arc-pro>` y en consecuencia el |DTD| también
262+
lo será y hay que buscarlo dentro del paquete |JAR|.
240263

241-
¿Qué hace exactamente el código que hemos propuesto? En principio, si
242-
no hay definido ninguno, no hace nada. En cambio, si hay definido uno,
243-
comprueba si el |DTD| se proporcionó con ruta absoluta (lo cual incluye una
244-
|URL| completa). Si fue así, respeta el valor y la validación se hará con el
245-
valor expresado en el archivo. En cambio, si la ruta era relativa, hay un
246-
problema: la librería entiende la ruta relativa no respecto al |XML| (que sería
247-
lo esperable), sino respecto al directorio de trabajo. Lo que hace nuestro
248-
código en este caso, es hacerla relativa respecto al |XML|.
264+
* Si no es así, se resuelve de forma normal la ruta relativa usando como base el
265+
|XML| (``baseURI``).
249266

250267
.. tip:: El argumento del constructor de `InputSource` también puede ser un
251268
:java-io:`Reader <Reader>`, así que si nuestra intención es que el programa no
@@ -386,6 +403,7 @@ si nuestra intención es usarla una sola vez:
386403
.. |DTD| replace:: :abbr:`DTD (Document Type Definition)`
387404
.. |JDK| replace:: :abbr:`JDK (Java Development Kit)`
388405
.. |URL| replace:: :abbr:`URL (Uniform Resource Locator)`
406+
.. |JAR| replace:: :abbr:`JAR (Java ARchive)`
389407

390408
.. |Node| replace:: :java-jaxp:`Node`
391409
.. |Element| replace:: :java-jaxp:`Element`
@@ -395,3 +413,6 @@ si nuestra intención es usarla una sola vez:
395413
.. |NamedNodeMap| replace:: :java-jaxp:`NamedNodeMap`
396414
.. |Document| replace:: :java-jaxp:`Document`
397415
.. |Path| replace:: :java-nio:`Path`
416+
.. |String| replace:: :java-io:`String <String>`
417+
.. |InputStream| replace:: :java-io:`InputStream <InputStream>`
418+
.. |File| replace:: :java-io:`File <File>`

0 commit comments

Comments
 (0)