package com.beowulfe.hap.impl.json; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; import javax.json.Json; import javax.json.JsonArrayBuilder; import javax.json.JsonObject; import javax.json.JsonObjectBuilder; import com.beowulfe.hap.HomekitAccessory; import com.beowulfe.hap.Service; import com.beowulfe.hap.characteristics.Characteristic; import com.beowulfe.hap.impl.HomekitRegistry; import com.beowulfe.hap.impl.http.HttpResponse; public class AccessoryController { private final HomekitRegistry registry; public AccessoryController(HomekitRegistry registry) { this.registry = registry; } public HttpResponse listing() throws Exception { JsonArrayBuilder accessories = Json.createArrayBuilder(); Map<Integer, List<CompletableFuture<JsonObject>>> accessoryServiceFutures = new HashMap<>(); for (HomekitAccessory accessory: registry.getAccessories()) { int iid = 0; List<CompletableFuture<JsonObject>> serviceFutures = new ArrayList<>(); for (Service service: registry.getServices(accessory.getId())) { serviceFutures.add(toJson(service, iid)); iid += service.getCharacteristics().size() + 1; } accessoryServiceFutures.put(accessory.getId(), serviceFutures); } Map<Integer, JsonArrayBuilder> serviceArrayBuilders = new HashMap<>(); for (Entry<Integer, List<CompletableFuture<JsonObject>>> entry: accessoryServiceFutures.entrySet()) { JsonArrayBuilder arr = Json.createArrayBuilder(); for (CompletableFuture<JsonObject> future: entry.getValue()) { arr.add(future.join()); } serviceArrayBuilders.put(entry.getKey(), arr); } for (HomekitAccessory accessory: registry.getAccessories()) { accessories.add(Json.createObjectBuilder().add("aid", accessory.getId()).add("services", serviceArrayBuilders.get(accessory.getId()))); } try(ByteArrayOutputStream baos = new ByteArrayOutputStream()) { Json.createWriter(baos).write( Json.createObjectBuilder().add("accessories", accessories).build() ); return new HapJsonResponse(baos.toByteArray()); } } private CompletableFuture<JsonObject> toJson(Service service, int interfaceId) throws Exception { JsonObjectBuilder builder = Json.createObjectBuilder() .add("iid", ++interfaceId) .add("type", service.getType()); List<Characteristic> characteristics = service.getCharacteristics(); Collection<CompletableFuture<JsonObject>> characteristicFutures = new ArrayList<>(characteristics.size()); for (Characteristic characteristic: characteristics) { characteristicFutures.add(characteristic.toJson(++interfaceId)); } return CompletableFuture.allOf(characteristicFutures.toArray(new CompletableFuture<?>[characteristicFutures.size()])) .thenApply(v -> { JsonArrayBuilder jsonCharacteristics = Json.createArrayBuilder(); characteristicFutures.stream().map(future -> future.join()).forEach(c -> jsonCharacteristics.add(c)); builder.add("characteristics", jsonCharacteristics); return builder.build(); }); } }