package de.persosim.simulator.cardobjects; import static org.globaltester.logging.BasicLogger.DEBUG; import static org.globaltester.logging.BasicLogger.log; import java.util.Collection; import java.util.LinkedList; import de.persosim.simulator.exception.ProcessingException; import de.persosim.simulator.platform.Iso7816; public class CardObjectUtils { /** * Perform a breadth-first-search beginning from the given search root and * return the first CardObject that matches all identifiers. * * @param searchRoot * object the search is started on * @param identifiers * set of identifiers that are required to match on the returned * element * @return first found element that matches all identifiers or * {@link NullCardObject} if no matching object can be found */ public static CardObject findObject(CardObject searchRoot, CardObjectIdentifier... identifiers) { LinkedList<CardObject> objectsToSearch = new LinkedList<>(); objectsToSearch.add(searchRoot); while (!objectsToSearch.isEmpty()) { CardObject curElem = objectsToSearch.removeFirst(); if (matches(curElem, identifiers)) { // current elem is the first match return curElem; } else { // add children to the list for (CardObject curChild : curElem.getChildren()) { objectsToSearch.addLast(curChild); } } } // no matching element found return new NullCardObject(); } /** * This method returns the only existing child {@link CardObject} of parent * parameter, that match all provided {@link CardObjectIdentifier}. * <p/> * It is expected that exactly one CardObject is returned (meaning that the * given Set of Identifiers is unambiguous). If no or more matching elements * are found an {@link IllegalArgumentException} is thrown. * * @param parent CardObject whose children should be searched * @param cardObjectIdentifier set of identifiers that are required to match on the returned element * @return the one and only child element of parent that matches all provided identifiers * @throws IllegalArgumentException if none or several matching children are found * */ public static CardObject getSpecificChild(CardObject parent, CardObjectIdentifier... cardObjectIdentifier) { Collection<CardObject> cardObjects = parent.findChildren(cardObjectIdentifier); // assume that selection is not ambiguous and can be performed implicitly switch (cardObjects.size()) { case 0: throw new ProcessingException(Iso7816.SW_6A88_REFERENCE_DATA_NOT_FOUND, "no matching selection found"); case 1: CardObject matchingCardObject = cardObjects.iterator().next(); log(CardObjectUtils.class, "selected " + matchingCardObject, DEBUG); return matchingCardObject; default: throw new ProcessingException(Iso7816.SW_6A88_REFERENCE_DATA_NOT_FOUND, "selection is ambiguous, more identifiers required"); } } /** * Check whether a given CardObject matches all identifiers * * @param obj * CardObject to be checked * @param cardObjectIdentifiers * set of identifiers that are required to match * @return true iff all identifiers match on obj */ public static boolean matches(CardObject obj, CardObjectIdentifier... cardObjectIdentifiers) { for (CardObjectIdentifier cardObjectIdentifier : cardObjectIdentifiers) { if (!cardObjectIdentifier.matches(obj)) { return false; } } return true; } /** * Recursively search all children of the given tree for a specific object. * * @param tree * object the search is started on * @param element * element to search for * @return true iff element is part of the tree */ public static boolean isObjectPartOfTree(CardObject tree, CardObject element) { LinkedList<CardObject> objectsToSearch = new LinkedList<>(); objectsToSearch.add(tree); while (!objectsToSearch.isEmpty()) { CardObject curElem = objectsToSearch.removeFirst(); if (curElem == element) { return true; } else { // add children to the list for (CardObject curChild : curElem.getChildren()) { objectsToSearch.add(curChild); } } } // no matching element found return false; } }