Java
Un programa en Java que usa la API con java.net.http, incluido en Java 11 y posteriores; el resto requiere Java 17. Enumera las variables etiquetadas de una plantilla, mide el dibujo que genera con los valores dados y lo exporta como PDF. Java no tiene un analizador de JSON propio, así que el programa termina con uno breve, suficiente para estas respuestas, y construye el JSON de sus solicitudes como texto; en un programa real, use una biblioteca como Jackson o Gson.
Descárguelo: Box.java.
// Box.java: list a template's inputs, measure it and export it as a PDF with the PiQ SaaS API.
// Java 17 or later; java.net.http, no libraries needed. Run with: java Box.java
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;
import java.util.*;
public class Box {
static final String TEMPLATE =
"L=400,\"Length\"\nW=300,\"Width\"\nP1=[L,0]\nP2=[L,W]\nP3=[0,W]\nPOLYLINE @1,[P0,P1,P2,P3],TRUE,0";
static final String KEY = System.getenv("PIQ_API_KEY");
static final String BASE = Objects.requireNonNullElse(System.getenv("PIQ_URL"), "https://saas.parametriq.co.uk")
.replaceAll("/$", "");
static final HttpClient HTTP = HttpClient.newHttpClient();
public static void main(String[] args) throws Exception {
if (KEY == null || KEY.isEmpty()) { System.err.println("Set PIQ_API_KEY to your API key."); System.exit(1); }
String storage = System.getenv("PIQ_STORAGE"); // optional: a registered storage's name
// the template itself, or (optional) where it is kept in your storage
String template = storage == null ? "\"template\":" + quote(TEMPLATE)
: "\"source\":{\"storage\":" + quote(storage) + ",\"key\":\"templates/box.piq\"}";
String values = "\"values\":{\"L\":500,\"W\":250}";
// 1. The template's labelled variables
var inputs = (Map<?, ?>) Json.parse(post("/inputs", "{" + template + "}").body());
for (var item : (List<?>) inputs.get("inputs")) {
var i = (Map<?, ?>) item;
System.out.printf("%s: %s (%s, %s)%n", i.get("name"), i.get("label"), i.get("kind"), i.get("value"));
}
// 2. The drawing measured, with the values given
var m = (Map<?, ?>) Json.parse(post("/measure", "{" + template + "," + values + "}").body());
Object cut = 0;
for (var layer : (List<?>) m.get("layers"))
if ("Cut".equals(((Map<?, ?>) layer).get("layer"))) cut = ((Map<?, ?>) layer).get("length");
System.out.printf("Size: %s x %s, cut length: %s%n", m.get("width"), m.get("height"), cut);
// 3. The drawing as a PDF
var pdf = HTTP.send(request("/export/pdf", "{" + template + "," + values + "}"),
HttpResponse.BodyHandlers.ofByteArray());
if (pdf.statusCode() >= 300) fail(pdf.statusCode(), new String(pdf.body(), "UTF-8"));
Files.write(Path.of("box.pdf"), pdf.body());
System.out.printf("Saved box.pdf (%s warnings)%n", pdf.headers().firstValue("X-PiQ-Warnings").orElse("?"));
// 4. Optional: the PDF saved to your storage instead of downloaded
if (storage != null) {
String destination = "\"destination\":{\"storage\":" + quote(storage)
+ ",\"key\":\"drawings/box.pdf\"},\"overwrite\":true";
var saved = (Map<?, ?>) Json.parse(
post("/save/pdf", "{" + template + "," + values + "," + destination + "}").body());
System.out.printf("Saved %s to %s (%s bytes)%n", saved.get("key"), saved.get("storage"), saved.get("size"));
}
}
static HttpRequest request(String path, String json) {
return HttpRequest.newBuilder(URI.create(BASE + path)).header("X-API-KEY", KEY)
.header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(json)).build();
}
static HttpResponse<String> post(String path, String json) throws Exception {
var response = HTTP.send(request(path, json), HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 300) fail(response.statusCode(), response.body());
return response;
}
static void fail(int status, String body) {
System.err.println("Error " + status);
if (!body.isEmpty()) { // a 401 has no body
try {
var problem = (Map<?, ?>) Json.parse(body);
for (var part : List.of("title", "detail"))
if (problem.get(part) != null) System.err.println(problem.get(part));
if (problem.get("errors") instanceof Map<?, ?> errors)
errors.forEach((field, messages) -> System.err.println(" " + field + ": "
+ String.join(" ", ((List<?>) messages).stream().map(String::valueOf).toList())));
} catch (RuntimeException e) { System.err.println(body); }
}
System.exit(1);
}
static String quote(String s) {
var b = new StringBuilder("\"");
for (char c : s.toCharArray())
if (c == '"' || c == '\\') b.append('\\').append(c);
else if (c < 0x20) b.append(String.format("\\u%04x", (int) c));
else b.append(c);
return b.append('"').toString();
}
/** Just enough JSON for this example: in a real program use a library such as Jackson or Gson. */
static class Json {
final String s; int i;
Json(String s) { this.s = s; }
static Object parse(String s) { return new Json(s).value(); }
void skip() { while (i < s.length() && Character.isWhitespace(s.charAt(i))) i++; }
Object value() {
skip();
char c = s.charAt(i);
if (c == '{') {
var map = new LinkedHashMap<String, Object>(); i++; skip();
if (s.charAt(i) == '}') { i++; return map; }
do { skip(); String k = (String) value(); skip(); i++; map.put(k, value()); skip(); }
while (s.charAt(i++) == ',');
return map;
}
if (c == '[') {
var list = new ArrayList<Object>(); i++; skip();
if (s.charAt(i) == ']') { i++; return list; }
do list.add(value()); while (skipThen() == ',');
return list;
}
if (c == '"') {
var b = new StringBuilder(); i++;
for (char d; (d = s.charAt(i++)) != '"'; )
if (d != '\\') b.append(d);
else switch (d = s.charAt(i++)) {
case 'n' -> b.append('\n'); case 't' -> b.append('\t'); case 'r' -> b.append('\r');
case 'b' -> b.append('\b'); case 'f' -> b.append('\f');
case 'u' -> { b.append((char) Integer.parseInt(s.substring(i, i + 4), 16)); i += 4; }
default -> b.append(d);
}
return b.toString();
}
int start = i;
while (i < s.length() && ",}] \r\n\t".indexOf(s.charAt(i)) < 0) i++;
String word = s.substring(start, i);
return switch (word) { case "true" -> true; case "false" -> false; case "null" -> null;
default -> word.matches("-?\\d+") ? (Object) Long.parseLong(word) : (Object) Double.parseDouble(word); };
}
char skipThen() { skip(); return s.charAt(i++); }
}
}
Cómo funciona
- Configuración. La clave se toma de
PIQ_API_KEY, la dirección dePIQ_URL(el propio servicio si no está definida) y, opcionalmente, el nombre de un almacenamiento dePIQ_STORAGE. Sin clave, el programa se detiene de inmediato. - La plantilla.
templatees el comienzo del JSON de cada solicitud: el texto de la plantilla comotemplateo, cuandoPIQ_STORAGEestá definida, dónde está guardada en su almacenamiento comosource.quoteconvierte un texto en una cadena JSON, escapando sus comillas y saltos de línea.valuesdaLyWpor nombre. requestconstruye unPOSTde JSON a una operación, con la clave en el encabezadoX-API-KEY.postlo envía y devuelve la respuesta como texto o, si no es correcta, pasa afail.failimprime el estado y después la descripción del problema: sutitle, sudetaily cada entrada deerrors, el campo y qué está mal en él. Un401no tiene cuerpo, así que el cuerpo solo se analiza cuando lo hay; un cuerpo que no es JSON se imprime tal cual. Después, el programa termina con1.- Inputs.
POST /inputssolo necesita la plantilla. Su respuesta se analiza en mapas y listas; cada uno de susinputstiene unname,label,kindyvalue. - Measure.
POST /measurecon los valores da elwidthy elheightdel dibujo, y las longitudes de sus líneas por capa enlayers; la longitud de corte es la longitud en la capaCut. - Export.
POST /export/pdfresponde con el propio PDF, no con JSON, así que se lee como bytes, se comprueba y se escribe enbox.pdf. El encabezadoX-PiQ-Warningsindica cuántas cosas no pudieron exportarse tal cual. - Save (opcional). Con un almacenamiento,
POST /save/pdfexporta el mismo dibujo y lo guarda en su almacenamiento endestination;"overwrite":truereemplaza un archivo que ya exista. Responde con dónde lo ha guardado y su tamaño. Jsonlee JSON enMap,List,String,Long,Double,Booleanynull. Confía en lo que recibe, lo cual es adecuado para las respuestas del servicio, pero para nada más.
Cómo ejecutarlo
Guarde el programa como Box.java y ejecútelo tal cual, sin compilarlo antes:
export PIQ_API_KEY=XXXX-XXXX-XXXX-XXXXX
java Box.java
Imprime las variables etiquetadas de la plantilla, el tamaño del dibujo y su longitud de corte, y guarda box.pdf:
L: Length (Number, 400)
W: Width (Number, 300)
D: Depth (Number, 300)
Size: 500 x 250, cut length: 1500
Saved box.pdf (0 warnings)
Con un valor que la plantilla no puede usar (por ejemplo, "L": "long"), imprime el problema y se detiene:
Error 400
One or more validation errors occurred.
Some of the values given can't be used.
L: L is a number.
Con una clave incorrecta, solo imprime Error 401: un 401 no tiene
descripción del problema.
Para probar la parte del almacenamiento, registre un almacenamiento (consulte
Registrar un almacenamiento), coloque en él una plantilla como templates/box.piq y
establezca PIQ_STORAGE con el nombre del almacenamiento. La plantilla se lee entonces desde su almacenamiento, y el
PDF también se guarda en él como drawings/box.pdf, reemplazando cualquier archivo que ya exista.
Consulte también: API, Inputs, Measure, Exportar un dibujo, Guardar en su almacenamiento, Registrar un almacenamiento, Clientes.