public List<FriendlyDescription> getFriendlyDescryptionsForAttributeType(URI attributeType) {
   AttributeDescription attrDescription = getAttributeDescriptionFromType(attributeType);
   if (attrDescription != null) {
     return attrDescription.getFriendlyAttributeName();
   } else
     throw new RuntimeException(
         "No attribute description for attribute type: " + attributeType.toString());
 }
  public MyCredentialSpecification(CredentialSpecification credSpec) {
    this.credSpec = credSpec;

    attributeDescriptions = new HashMap<URI, AttributeDescription>();
    for (AttributeDescription ad : credSpec.getAttributeDescriptions().getAttributeDescription()) {
      attributeDescriptions.put(ad.getType(), ad);
    }

    if (credSpec.isRevocable()) {
      if (!attributeDescriptions.containsKey(URI.create(REVOCATION_HANDLE))) {
        throw new RuntimeException(
            "Credential is revocable, yet it does not contain a revocation handle.");
      }
    }
  }
  @Override
  public boolean verifyToken(PresentationToken t) throws TokenVerificationException {

    ObjectFactory of = new ObjectFactory();
    // System.out.println("Bridging verify token: "+t);
    try {
      //            String xml = XmlUtils.toXml(of.createPresentationToken(t), false);
      //            System.out.println(xml+"\n\n");

      String[] pseudonymEngines = this.getPseudonymEngines(t);

      boolean tokenContainsUProve = false;
      PresentationTokenWithCommitments idemixToken = of.createPresentationTokenWithCommitments();
      PresentationToken uproveToken = of.createPresentationToken();
      if (t.getVersion() == null) {
        uproveToken.setVersion("1.0");
        idemixToken.setVersion("1.0");
      } else {
        idemixToken.setVersion(t.getVersion());
        uproveToken.setVersion(t.getVersion());
      }
      PresentationTokenDescription desc = t.getPresentationTokenDescription();
      PresentationTokenDescription iDesc = of.createPresentationTokenDescription();
      PresentationTokenDescription uDesc = of.createPresentationTokenDescription();
      iDesc.setMessage(desc.getMessage());
      uDesc.setMessage(desc.getMessage());
      iDesc.setPolicyUID(desc.getPolicyUID());
      uDesc.setPolicyUID(desc.getPolicyUID());
      iDesc.setTokenUID(desc.getTokenUID());
      uDesc.setTokenUID(desc.getTokenUID());

      for (int i = 0; i < pseudonymEngines.length; i++) {
        PseudonymInToken pit = t.getPresentationTokenDescription().getPseudonym().get(i);
        if ("UPROVE".equals(pseudonymEngines[i])) {
          uDesc.getPseudonym().add(pit);
        } else {
          iDesc.getPseudonym().add(pit);
        }
      }

      this.verifierRevocation.clearCredentialInToken();

      Set<URI> idemixCredentialAliases = new HashSet<URI>();
      Set<URI> uproveCredentialAliases = new HashSet<URI>();
      for (CredentialInToken cit : desc.getCredential()) {

        this.verifierRevocation.addCredentialInToken(cit);

        /*
        try{
        	System.out.println("original: "+XmlUtils.toXml(of.createCredentialInToken(cit)));
        }catch(Exception e){System.out.println("failed to print original cit");};
         */
        if ((this.keyManager.getIssuerParameters(cit.getIssuerParametersUID()))
            .getAlgorithmID()
            .equals(CryptoUriUtil.getIdemixMechanism())) {
          idemixCredentialAliases.add(cit.getAlias());
          iDesc.getCredential().add(cit);
        } else {
          uproveCredentialAliases.add(cit.getAlias());
          uDesc.getCredential().add(cit);
          tokenContainsUProve = true;

          // Add issuer parameters to Idemix Structure store
          try {
            this.storeUProveIssuerParameters(cit.getIssuerParametersUID());
          } catch (Exception e) {
            System.out.println(
                "Failed to store UProve issuer parameters in Idemix structure store");
            throw new RuntimeException(e);
          }
        }
      }

      for (AttributePredicate ap : desc.getAttributePredicate()) {
        for (Object o : ap.getAttributeOrConstantValue()) {
          if (o instanceof AttributePredicate.Attribute) {
            iDesc.getAttributePredicate().add(ap);
            break;
          }
        }
      }

      // TODO This might require some changes to work with revocation
      for (VerifierDrivenRevocationInToken vdr : desc.getVerifierDrivenRevocation()) {
        for (AttributeInRevocation air : vdr.getAttribute()) {
          if (idemixCredentialAliases.contains(air.getCredentialAlias())) {
            iDesc.getVerifierDrivenRevocation().add(vdr);
            break;
          } else {
            uDesc.getVerifierDrivenRevocation().add(vdr);
          }
        }
      }

      // TODO Look at the uprove crypto evidence, if there are committed indices,
      // check with cred spec if they are for revocation handles
      // if so, do some stuff that allows poltransl and the other idemix parts to work

      idemixToken.setPresentationTokenDescriptionWithCommitments(this.addCommitments(iDesc));
      uproveToken.setPresentationTokenDescription(uDesc);

      boolean verifies = false;
      CryptoParams tcp = t.getCryptoEvidence();
      CryptoParams icp = of.createCryptoParams();
      boolean cryptoEvidenceContainsIdemix = false;
      for (Object o : tcp.getAny()) {
        try {
          if (o instanceof JAXBElement) {
            JAXBElement<?> jaxb = (JAXBElement<?>) o;
            Object wrapped = jaxb.getValue();
            if (wrapped instanceof CredentialInTokenWithCommitments) {
              cryptoEvidenceContainsIdemix = true;
              CredentialInTokenWithCommitments citwc = (CredentialInTokenWithCommitments) wrapped;
              idemixToken
                  .getPresentationTokenDescriptionWithCommitments()
                  .getCredential()
                  .add(
                      citwc); // (CredentialInTokenWithCommitments)XmlUtils.getObjectFromXML(credIn,
                              // false));
            } else {
              System.err.println(
                  "Element is JaxB : "
                      + jaxb.getValue()
                      + " : "
                      + jaxb.getDeclaredType()
                      + " : "
                      + jaxb.getScope()
                      + " : "
                      + jaxb.getName());
            }
            continue;
          }
          Element e = (Element) o;
          String elementName = e.getLocalName() != null ? e.getLocalName() : e.getNodeName();
          if ("UProveCredentialAndPseudonym".equals(elementName)) {
            String credAlias =
                ((Element) e.getElementsByTagName("Proof").item(0))
                    .getElementsByTagName("CredentialAlias")
                    .item(0)
                    .getTextContent();
            CredentialSpecification credSpec = null;
            CredentialInToken c = null;

            for (CredentialInToken cit : t.getPresentationTokenDescription().getCredential()) {
              if (cit.getAlias().toString().equals(credAlias)) {
                credSpec = this.keyManager.getCredentialSpecification(cit.getCredentialSpecUID());
                c = cit;
                break;
              }
            }

            if (credSpec == null) {
              throw new RuntimeException("Could not find credential specification.");
            }

            List<Integer> inspectableAttributes = new ArrayList<Integer>();
            Map<Integer, URI> indexToInspectorKey = new HashMap<Integer, URI>();
            Map<Integer, URI> indexToAttributeType = new HashMap<Integer, URI>();
            // TODO here we have to also look at any inspectable attributes.
            // If there are any, we need to create an inspectable information element etc.
            int revocationindex = -1;
            for (int i = 0;
                i < credSpec.getAttributeDescriptions().getAttributeDescription().size();
                i++) {
              AttributeDescription ad =
                  credSpec.getAttributeDescriptions().getAttributeDescription().get(i);

              if (ad.getType()
                  .toString()
                  .equals("http://abc4trust.eu/wp2/abcschemav1.0/revocationhandle")) {
                revocationindex = i;
              }
              for (AttributeInToken da : c.getDisclosedAttribute()) {
                if (da.getAttributeType().equals(ad.getType())
                    && (da.getInspectorPublicKeyUID() != null)) {
                  inspectableAttributes.add(i);
                  indexToInspectorKey.put(i, da.getInspectorPublicKeyUID());
                  indexToAttributeType.put(i, da.getAttributeType());
                }
              }
            }
            Set<Integer> committedValues = new HashSet<Integer>();
            committedValues.addAll(inspectableAttributes);
            if (!committedValues.contains(revocationindex) && (revocationindex != -1)) {
              committedValues.add(revocationindex);
            }
            Map<Integer, Integer> indexToIndexInProof = this.mapIndices(committedValues);

            if (e.getElementsByTagName("CommittedAttributesIndices").getLength() > 0) {
              Element cai = (Element) e.getElementsByTagName("CommittedAttributesIndices").item(0);
              NodeList nl = cai.getChildNodes();
              for (int j = 0; j < nl.getLength(); j++) {
                Element ind = null;
                try {
                  ind = (Element) nl.item(j);
                } catch (ClassCastException ex) {
                  // If we end up here, it is most likely because we got a TextElement which is
                  // empty due
                  // to malformed xml (such as \r or \n)
                  continue;
                }
                int committedIndex = Integer.parseInt(ind.getTextContent()) - 1;
                Element root = null;
                // make addToRoot method, to allow for inspectable revocationinformation
                if (committedIndex == revocationindex) {
                  root = ind.getOwnerDocument().createElement("RevocationInformation");
                } else if (inspectableAttributes.contains(committedIndex)) {
                  root = ind.getOwnerDocument().createElement("InspectableInformation");
                  root.setAttribute(
                      "InspectorPublicKey", indexToInspectorKey.get(committedIndex).toString());
                  root.setAttribute(
                      "AttributeType", indexToAttributeType.get(committedIndex).toString());
                } else {
                  // TODO: @Michael - explain this code a little :)
                  continue;
                }
                root.setAttribute("CredentialAlias", c.getAlias().toString());
                root.setAttribute("CredentialSpecUID", credSpec.getSpecificationUID().toString());
                root.setAttribute("IssuerParamsUID", c.getIssuerParametersUID().toString());

                Element tilde = root.getOwnerDocument().createElement("TildeO");
                root.appendChild(tilde);
                NodeList tildes = e.getElementsByTagName("TildeO").item(0).getChildNodes();
                //
                // System.out.println("got the tildeO nodes: "+tildes.getLength());

                tilde.appendChild(
                    tildes.item(indexToIndexInProof.get(committedIndex)).cloneNode(true));
                tilde = root.getOwnerDocument().createElement("TildeValues");
                root.appendChild(tilde);
                tildes = e.getElementsByTagName("TildeValues").item(0).getChildNodes();
                tilde.appendChild(
                    tildes.item((indexToIndexInProof.get(committedIndex) * 3)).cloneNode(true));
                icp.getAny().add(root);
              }
            }
          }

          if ("IdmxProof".equals(elementName)) {
            cryptoEvidenceContainsIdemix = true;
            icp.getAny().add(o);
          }
          if ("CredentialInTokenWithCommitments".equals(elementName)
              || "abc:CredentialInTokenWithCommitments".equals(elementName)) {
            cryptoEvidenceContainsIdemix = true;
            // magic code adding the CrednetialInToken
            TransformerFactory transfac = TransformerFactory.newInstance();
            Transformer trans = transfac.newTransformer();
            trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            trans.setOutputProperty(OutputKeys.INDENT, "yes");

            // create string from xml tree
            StringWriter sw = new StringWriter();
            StreamResult result = new StreamResult(sw);
            DOMSource source = new DOMSource(e.getOwnerDocument());
            trans.transform(source, result);
            String xmlString = sw.toString();

            InputStream credIn = new ByteArrayInputStream(xmlString.getBytes());
            idemixToken
                .getPresentationTokenDescriptionWithCommitments()
                .getCredential()
                .add((CredentialInTokenWithCommitments) XmlUtils.getObjectFromXML(credIn, false));
          }
          if ("VerifiableEncryption".equals(elementName)) {
            icp.getAny().add(o);
          }
        } catch (Exception e) {
          e.printStackTrace();
          // TODO @jdn, I think your revocation code causes some some serialization problems
          // /Michael
          // throw new RuntimeException(e);
        }
      }

      if (cryptoEvidenceContainsIdemix) {
        idemixToken.setCryptoEvidence(icp);

        //    System.out.println("\n\nNow verifying idmtoken!!");
        //	System.out.println(XmlUtils.toXml(of.createPresentationTokenWithCommitments(idemixToken),
        // false)+"\n\n");

        // System.out.println("about to call idmix engine for verification");
        // System.out.println("we have "+idemixToken.getCryptoEvidence().getAny().size()+" crypto
        // evidence");
        if (idemixToken.getCryptoEvidence().getAny().size() == 0) {
          verifies = true;
        } else {
          verifies = this.idemixEngine.verifyTokenWithCommitments(idemixToken);
        }
        System.out.println("idemix verifies: " + verifies);
      }

      if (tokenContainsUProve) {
        //                CryptoParams tcp = t.getCryptoEvidence();
        tcp = t.getCryptoEvidence();
        CryptoParams ucp = of.createCryptoParams();
        for (Object o : tcp.getAny()) {
          try {
            Element e = (Element) o;
            if (e.getNodeName().startsWith("UProve")) {
              ucp.getAny().add(o);
            }
          } catch (Exception e) {
          }
        }
        uproveToken.setCryptoEvidence(ucp);
        // System.out.println("Now verifying uprove");

        // xml = XmlUtils.toXml(of.createPresentationToken(uproveToken), false);
        // System.out.println(xml+"\n\n");

        boolean ver = this.uproveEngine.verifyToken(uproveToken);
        // System.out.println("uprove verifies: "+ver);
        if (cryptoEvidenceContainsIdemix) {
          verifies = verifies && ver;
        } else {
          verifies = ver;
        }
      }

      // System.out.println("DELEGATION VERIFIER.verifies:::: "+verifies);
      return verifies;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return false;
  }
  /**
   * Check if the current credential description matches the given credential specification. The
   * order of attributes in the credential does not matter.
   *
   * @param credSpec The credential specification to validate against
   */
  public void validateOrThrow(CredentialDescription credDesc) {
    Set<URI> seenAttributeTypes = new HashSet<URI>();
    for (Attribute ad : credDesc.getAttribute()) {
      URI attributeType = ad.getAttributeDescription().getType();
      if (!seenAttributeTypes.add(attributeType)) {
        String errorMessage = "Duplicate attribute type " + attributeType + ".";
        throw new RuntimeException(errorMessage);
      }
    }

    if (credDesc.getAttribute().size() != attributeDescriptions.size()) {
      StringBuilder errorMessage = new StringBuilder();
      errorMessage.append("Created Credential size does not match spec. ");
      errorMessage.append("Actual size: " + credDesc.getAttribute().size() + ".");
      errorMessage.append("Expected size:" + attributeDescriptions.size() + ".");
      errorMessage.append("Expected types: ");
      for (URI key : attributeDescriptions.keySet()) {
        errorMessage.append(key + ",");
      }
      errorMessage.append("  Actual types: ");
      for (Attribute ad : credDesc.getAttribute()) {
        errorMessage.append(ad.getAttributeDescription().getType() + ",");
      }
      throw new RuntimeException(errorMessage.toString());
    }

    for (Attribute ad : credDesc.getAttribute()) {
      URI attributeType = ad.getAttributeDescription().getType();
      AttributeDescription expectedAttDesc = attributeDescriptions.get(attributeType);

      if (expectedAttDesc == null) {
        String errorMessage = "Unknown attribute type: " + attributeType;
        throw new RuntimeException(errorMessage);
      }

      URI expectedDataType = expectedAttDesc.getDataType();
      URI actualDataType = ad.getAttributeDescription().getDataType();
      if (!expectedDataType.equals(actualDataType)) {
        String errorMessage =
            "Wrong data type in "
                + attributeType
                + ". Expected "
                + expectedDataType
                + " actual "
                + actualDataType;
        throw new RuntimeException(errorMessage);
      }

      URI expectedEncoding = expectedAttDesc.getEncoding();
      URI actualEncoding = ad.getAttributeDescription().getEncoding();
      if (!expectedEncoding.equals(actualEncoding)) {
        String errorMessage =
            "Wrong encoding in "
                + attributeType
                + ". Expected "
                + expectedEncoding
                + " actual "
                + actualEncoding;
        throw new RuntimeException(errorMessage);
      }

      URI compatibleDatatype = MyAttributeEncodingFactory.getDatatypeFromEncoding(actualEncoding);
      if (!compatibleDatatype.equals(actualDataType)) {
        String errorMessage =
            "Incompatible dataType in "
                + attributeType
                + " for encoding "
                + actualEncoding
                + ". Expected "
                + compatibleDatatype
                + " actual "
                + actualDataType;
        throw new RuntimeException(errorMessage);
      }
    }
  }