package com.evolveum.midpoint.schema.util;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import javax.xml.bind.JAXBElement;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.xnode.RootXNode;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.SerializationContext;
import com.evolveum.midpoint.prism.SerializationOptions;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.prism.xnode.PrimitiveXNode;
import com.evolveum.midpoint.prism.xnode.XNode;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.EntryType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectFactory;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ParamsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UnknownJavaObjectType;
import com.evolveum.prism.xml.ns._public.types_3.RawType;
public class ParamsTypeUtil {
public static ParamsType toParamsType(Map<String, Serializable> paramsMap){
Set<Entry<String, Serializable>> params = paramsMap.entrySet();
if (!params.isEmpty()) {
ParamsType paramsType = new ParamsType();
for (Entry<String, Serializable> entry : params) {
paramsType.getEntry().add(createEntryElement(entry.getKey(),entry.getValue()));
}
return paramsType;
}
return null;
}
public static ParamsType toParamsType(Map<String, Serializable> paramsMap, PrismContext prismContext) throws SchemaException{
Set<Entry<String, Serializable>> params = paramsMap.entrySet();
if (!params.isEmpty()) {
ParamsType paramsType = new ParamsType();
for (Entry<String, Serializable> entry : params) {
paramsType.getEntry().add(createEntryElement(entry, prismContext));
}
return paramsType;
}
return null;
}
private static EntryType createEntryElement(Entry<String, Serializable> entry, PrismContext prismContext) throws SchemaException {
EntryType result = new EntryType();
result.setKey(entry.getKey());
if (XmlTypeConverter.canConvert(entry.getValue().getClass())){
return createEntryElement(entry.getKey(), entry.getValue());
} else {
RootXNode xnode = prismContext.xnodeSerializer()
.options(SerializationOptions.createSerializeReferenceNames())
.serializeAnyData(entry.getValue(), SchemaConstants.C_PARAM_VALUE);
return createEntryElement(entry.getKey(), new RawType(xnode, prismContext));
}
}
public static Map<String, Serializable> fromParamsType(ParamsType paramsType, PrismContext prismContext) throws SchemaException{
if (paramsType != null) {
Map<String, Serializable> params = new HashMap<String, Serializable>();
Serializable realValue = null;
for (EntryType entry : paramsType.getEntry()) {
if (entry.getEntryValue() != null){
Serializable value = (Serializable) entry.getEntryValue().getValue();
if (value instanceof RawType){
XNode xnode = ((RawType) value).getXnode();
if (xnode instanceof PrimitiveXNode){
realValue = ((PrimitiveXNode) xnode).getGuessedFormattedValue();
}
} else {
realValue = value;
}
}
params.put(entry.getKey(), (Serializable) (realValue));
}
return params;
}
return null;
}
public static Map<String, Serializable> fromParamsType(ParamsType paramsType) {
if (paramsType != null) {
Map<String, Serializable> params = new HashMap<String, Serializable>();
Serializable realValue = null;
for (EntryType entry : paramsType.getEntry()) {
if (entry.getEntryValue() != null){
// Serializable value = (Serializable) entry.getEntryValue().getValue();
// if (value instanceof RawType){
// XNode xnode = ((RawType) value).getXnode();
// if (xnode instanceof PrimitiveXNode){
// realValue = ((PrimitiveXNode) xnode).getGuessedFormattedValue();
// }
// } else {
// realValue = value;
// }
// }
params.put(entry.getKey(), (Serializable) entry.getEntryValue());
}
}
return params;
}
return null;
}
/**
* Temporary workaround, brutally hacked -- so that the conversion
* of OperationResult into OperationResultType 'somehow' works, at least to the point
* where when we:
* - have OR1
* - serialize it into ORT1
* - then deserialize into OR2
* - serialize again into ORT2
* so we get ORT1.equals(ORT2) - at least in our simple test case :)
*
* FIXME: this should be definitely reworked
*
* @param entry
* @return
*/
private static EntryType createEntryElement(String key, Serializable value) {
EntryType entryType = new EntryType();
entryType.setKey(key);
if (value != null) {
Document doc = DOMUtil.getDocument();
if (value instanceof ObjectType && ((ObjectType)value).getOid() != null) {
// Store only reference on the OID. This is faster and getObject can be used to retrieve
// the object if needed. Although is does not provide 100% accuracy, it is a good tradeoff.
setObjectReferenceEntry(entryType, ((ObjectType)value));
// these values should be put 'as they are', in order to be deserialized into themselves
} else if (value instanceof String || value instanceof Integer || value instanceof Long) {
entryType.setEntryValue(new JAXBElement<Serializable>(SchemaConstants.C_PARAM_VALUE, Serializable.class, value));
} else if (XmlTypeConverter.canConvert(value.getClass())) {
// try {
// entryType.setEntryValue(new JXmlTypeConverter.toXsdElement(value, SchemaConstants.C_PARAM_VALUE, doc, true));
// } catch (SchemaException e) {
// LOGGER.error("Cannot convert value {} to XML: {}",value,e.getMessage());
// setUnknownJavaObjectEntry(entryType, value);
// }
} else if (value instanceof Element || value instanceof JAXBElement<?>) {
entryType.setEntryValue((JAXBElement<?>) value);
// FIXME: this is really bad code ... it means that 'our' JAXB object should be put as is
} else if ("com.evolveum.midpoint.xml.ns._public.common.common_3".equals(value.getClass().getPackage().getName())) {
JAXBElement<Object> o = new JAXBElement<Object>(SchemaConstants.C_PARAM_VALUE, Object.class, value);
entryType.setEntryValue(o);
} else {
setUnknownJavaObjectEntry(entryType, value);
}
}
return entryType;
}
private static void setObjectReferenceEntry(EntryType entryType, ObjectType objectType) {
ObjectReferenceType objRefType = new ObjectReferenceType();
objRefType.setOid(objectType.getOid());
ObjectTypes type = ObjectTypes.getObjectType(objectType.getClass());
if (type != null) {
objRefType.setType(type.getTypeQName());
}
JAXBElement<ObjectReferenceType> element = new JAXBElement<ObjectReferenceType>(
SchemaConstants.C_OBJECT_REF, ObjectReferenceType.class, objRefType);
// entryType.setAny(element);
}
private static void setUnknownJavaObjectEntry(EntryType entryType, Serializable value) {
UnknownJavaObjectType ujo = new UnknownJavaObjectType();
ujo.setClazz(value.getClass().getName());
ujo.setToString(value.toString());
entryType.setEntryValue(new ObjectFactory().createUnknownJavaObject(ujo));
}
}