package org.keycloak.protocol.cas.utils;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAnyElement;
import jakarta.xml.bind.annotation.XmlSchema;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import org.keycloak.protocol.cas.representations.CASServiceResponse;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Transforms the attribute map of the AuthenticationSuccess object (which can contain either simple values or
* lists) to a flat list of XML nodes, where the key is the node name.
* Lists output multiple XML nodes with the same name.
*/
public final class AttributesMapAdapter extends XmlAdapter> {
@Override
public AttributeWrapperType marshal(Map v) throws Exception {
return new AttributeWrapperType(v);
}
@Override
public Map unmarshal(AttributeWrapperType v) throws Exception {
throw new IllegalStateException("not implemented");
}
@XmlAccessorType(XmlAccessType.FIELD)
static class AttributeWrapperType {
@XmlAnyElement
private final List> elements;
AttributeWrapperType(Map attributes) {
this.elements = new ArrayList<>();
for (Map.Entry entry : attributes.entrySet()) {
if (entry.getValue() instanceof Collection) {
for (Object item : ((Collection) entry.getValue())) {
addElement(entry.getKey(), item);
}
} else {
addElement(entry.getKey(), entry.getValue());
}
}
}
private void addElement(String name, Object value) {
if (value != null) {
String namespace = CASServiceResponse.class.getPackage().getAnnotation(XmlSchema.class).namespace();
elements.add(new JAXBElement<>(new QName(namespace, name), String.class, value.toString()));
}
}
}
}