com.evolveum.midpoint.prism.util.JaxbTestUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.prism.util.JaxbTestUtil.java

Source

/*
 * Copyright (c) 2010-2014 Evolveum
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.evolveum.midpoint.prism.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismContainerDefinition;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.Validate;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.evolveum.midpoint.prism.Objectable;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.schema.SchemaDescription;
import com.evolveum.midpoint.prism.schema.SchemaRegistry;
import com.evolveum.midpoint.prism.xml.DynamicNamespacePrefixMapper;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.JAXBUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;

/**
 * DEPRECATED as of May 12, 2014. MidPoint data structures are not to be processed by JAXB any more.
 * (The last drop was the inability to hide RawType from externally-visible model service WSDL.
 * The solution devised, based on @Raw type, prevents JAXB from correctly parsing any structures that
 * contain RawType elements.)
 *
 * So, don't use JaxbTestUtil even for testing purposes. Use PrismTestUtil instead.
 *
 * ===
 * Original description:
 *
 * JAXB testing util. Only for use in tests. DO NOT USE IN PRODUCTION CODE.
 * This util is used to test the ablility of prism JAXB representation to be used by
 * native (Sun) JAXB code.
 * 
 * Note: this is what used to be PrismJaxbProcessor. Therefore there may be still a lot of junk to clean up.
 * 
 * @author Radovan Semancik
 */
@Deprecated
public class JaxbTestUtil {

    private static final QName DEFAULT_ELEMENT_NAME = new QName(
            "http://midpoint.evolveum.com/xml/ns/test/whatever-1.xsd", "whatever");

    private static final Trace LOGGER = TraceManager.getTrace(JaxbTestUtil.class);

    private PrismContext prismContext;
    private JAXBContext context;

    private static JaxbTestUtil instance;

    public static JaxbTestUtil getInstance() {
        if (instance == null) {
            instance = new JaxbTestUtil();
            instance.prismContext = PrismTestUtil.getPrismContext();
            instance.initialize();
        }
        return instance;
    }

    private JaxbTestUtil() {
    }

    public PrismContext getPrismContext() {
        return prismContext;
    }

    private SchemaRegistry getSchemaRegistry() {
        return prismContext.getSchemaRegistry();
    }

    public void initialize() {
        StringBuilder sb = new StringBuilder();
        Iterator<Package> iterator = getSchemaRegistry().getCompileTimePackages().iterator();
        while (iterator.hasNext()) {
            Package jaxbPackage = iterator.next();
            sb.append(jaxbPackage.getName());
            if (iterator.hasNext()) {
                sb.append(":");
            }
        }
        String jaxbPaths = sb.toString();
        if (jaxbPaths.isEmpty()) {
            LOGGER.debug("No JAXB paths, skipping creation of JAXB context");
        } else {
            try {
                context = JAXBContext.newInstance(jaxbPaths);
            } catch (JAXBException ex) {
                throw new SystemException("Couldn't create JAXBContext for: " + jaxbPaths, ex);
            }
        }
    }

    public JAXBContext getContext() {
        return context;
    }

    public void setContext(JAXBContext context) {
        this.context = context;
    }

    public boolean isJaxbClass(Class<?> clazz) {
        if (clazz == null) {
            throw new IllegalArgumentException("No class, no fun");
        }
        if (clazz.getPackage() == null) {
            // No package: this is most likely a primitive type and definitely
            // not a JAXB class
            return false;
        }
        for (Package jaxbPackage : getSchemaRegistry().getCompileTimePackages()) {
            if (jaxbPackage.equals(clazz.getPackage())) {
                return true;
            }
        }
        return false;
    }

    public boolean canConvert(Class<?> clazz) {
        return isJaxbClass(clazz);
    }

    public boolean canConvert(QName xsdType) {
        SchemaDescription schemaDesc = getSchemaRegistry()
                .findSchemaDescriptionByNamespace(xsdType.getNamespaceURI());
        if (schemaDesc == null) {
            return false;
        }
        if (schemaDesc.getCompileTimeClassesPackage() == null) {
            return false;
        }
        // We may be answering "yes" to a broader set of types that we can really convert.
        // But that does not matter that much. If the type is in the correct namespace
        // then either we can convert it or nobody can.
        return true;
        // Following code is not really correct. There are XSD types that we can convert and there is
        // no complexTypeDefinition for then in our parsed schema. E.g. all the property JAXB types.
        //      ComplexTypeDefinition complexTypeDefinition = schema.findComplexTypeDefinition(xsdType);
        //      return complexTypeDefinition != null;
    }

    public <T> Class<T> getCompileTimeClass(QName xsdType) {
        SchemaDescription desc = getSchemaRegistry().findSchemaDescriptionByNamespace(xsdType.getNamespaceURI());
        if (desc == null) {
            return null;
        }
        Map<QName, Class<?>> map = desc.getXsdTypeTocompileTimeClassMap();
        if (map == null) {
            return null;
        }
        return (Class<T>) map.get(xsdType);
    }

    public <T> T toJavaValue(Element element, Class<T> typeClass) throws JAXBException {
        QName type = JAXBUtil.getTypeQName(typeClass);
        return (T) toJavaValue(element, type);
    }

    /**
     * Used to convert property values from DOM 
     */
    public Object toJavaValue(Element element, QName xsdType) throws JAXBException {
        Class<?> declaredType = getCompileTimeClass(xsdType);
        if (declaredType == null) {
            // This may happen if the schema is runtime and there is no associated compile-time class
            throw new SystemException("Cannot determine Java type for " + xsdType);
        }
        JAXBElement<?> jaxbElement = createUnmarshaller().unmarshal(element, declaredType);
        Object object = jaxbElement.getValue();
        return object;
    }

    private Marshaller createMarshaller(Map<String, Object> jaxbProperties) throws JAXBException {
        Marshaller marshaller = context.createMarshaller();
        // set default properties
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        DynamicNamespacePrefixMapper namespacePrefixMapper = getSchemaRegistry().getNamespacePrefixMapper().clone();
        namespacePrefixMapper.setAlwaysExplicit(true);
        marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", namespacePrefixMapper);
        // set custom properties
        if (jaxbProperties != null) {
            for (Entry<String, Object> property : jaxbProperties.entrySet()) {
                marshaller.setProperty(property.getKey(), property.getValue());
            }
        }

        return marshaller;
    }

    /**
     * Allow for pooling and other fancy stuff. Now it dumb, creates in every call.
     */
    private Marshaller getMarshaller() throws JAXBException {
        return createMarshaller(null);
    }

    private Unmarshaller createUnmarshaller() throws JAXBException {
        return context.createUnmarshaller();
    }

    /**
     * Allow for pooling and other fancy stuff. Now it dumb, creates in every call.
     */
    public Unmarshaller getUnmarshaller() throws JAXBException {
        return createUnmarshaller();
    }

    public String marshalToString(Objectable objectable) throws JAXBException {
        return marshalToString(objectable, new HashMap<String, Object>());
    }

    public String marshalToString(Objectable objectable, Map<String, Object> properties) throws JAXBException {
        QName elementQName = determineElementQName(objectable);
        JAXBElement<Object> jaxbElement = new JAXBElement<Object>(elementQName, (Class) objectable.getClass(),
                objectable);
        return marshalElementToString(jaxbElement, properties);
    }

    public String marshalElementToString(JAXBElement<?> jaxbElement) throws JAXBException {
        return marshalElementToString(jaxbElement, new HashMap<String, Object>());
    }

    public String marshalElementToString(JAXBElement<?> jaxbElement, Map<String, Object> properties)
            throws JAXBException {
        StringWriter writer = new StringWriter();
        Marshaller marshaller = getMarshaller();
        for (Entry<String, Object> entry : properties.entrySet()) {
            marshaller.setProperty(entry.getKey(), entry.getValue());
        }
        marshaller.marshal(jaxbElement, writer);
        return writer.getBuffer().toString();
    }

    public String marshalElementToString(Object element) throws JAXBException {
        return marshalElementToString(element, new HashMap<String, Object>());
    }

    /**
     * Serializes DOM or JAXB element to string
     */
    public String marshalElementToString(Object element, Map<String, Object> properties) throws JAXBException {
        if (element == null) {
            return null;
        }
        if (element instanceof Element) {
            return DOMUtil.serializeDOMToString((Element) element);
        } else if (element instanceof JAXBElement) {
            return marshalElementToString((JAXBElement<?>) element, properties);
        } else {
            throw new IllegalArgumentException("Unsupported element type " + element.getClass().getName());
        }
    }

    /**
     * Serializes DOM or JAXB element to string, using specified elementName if needed.
     */
    public String marshalElementToString(Object element, QName elementName) throws JAXBException {
        if (element == null) {
            return null;
        }
        if (element instanceof Element) {
            return DOMUtil.serializeDOMToString((Element) element);
        } else if (element instanceof JAXBElement) {
            return marshalElementToString((JAXBElement<?>) element);
        } else {
            JAXBElement<Object> jaxbElement = new JAXBElement<Object>(elementName, Object.class, element);
            return marshalElementToString(jaxbElement);
        }
    }

    public void marshalToDom(Objectable objectable, Node parentNode) throws JAXBException {
        QName elementQName = determineElementQName(objectable);
        JAXBElement<Object> jaxbElement = new JAXBElement<Object>(elementQName, (Class) objectable.getClass(),
                objectable);
        marshalElementToDom(jaxbElement, parentNode);
    }

    public void marshalElementToDom(JAXBElement<?> jaxbElement, Node parentNode) throws JAXBException {
        getMarshaller().marshal(jaxbElement, parentNode);
    }

    public <T> Element marshalElementToDom(JAXBElement<T> jaxbElement, Document doc) throws JAXBException {
        if (doc == null) {
            doc = DOMUtil.getDocument();
        }

        Element element = doc.createElementNS(jaxbElement.getName().getNamespaceURI(),
                jaxbElement.getName().getLocalPart());
        marshalElementToDom(jaxbElement, element);

        return (Element) element.getFirstChild();
    }

    public <T> Element marshalObjectToDom(T jaxbObject, QName elementQName) throws JAXBException {
        return marshalObjectToDom(jaxbObject, elementQName, (Document) null);
    }

    public String marshalContainerableToString(Containerable containerable) throws JAXBException {
        return marshalObjectToString(containerable, determineElementQName(containerable));
    }

    public <T> String marshalObjectToString(T jaxbObject, QName elementQName) throws JAXBException {
        JAXBElement<Object> jaxbElement = new JAXBElement<Object>(elementQName, (Class) jaxbObject.getClass(),
                jaxbObject);
        return marshalElementToString(jaxbElement);
    }

    public <T> Element marshalObjectToDom(T jaxbObject, QName elementQName, Document doc) throws JAXBException {
        if (doc == null) {
            doc = DOMUtil.getDocument();
        }

        JAXBElement<T> jaxbElement = new JAXBElement<T>(elementQName, (Class<T>) jaxbObject.getClass(), jaxbObject);
        Element element = doc.createElementNS(elementQName.getNamespaceURI(), elementQName.getLocalPart());
        marshalElementToDom(jaxbElement, element);

        return (Element) element.getFirstChild();
    }

    public <T> void marshalObjectToDom(T jaxbObject, QName elementQName, Element parentElement)
            throws JAXBException {

        JAXBElement<T> jaxbElement = new JAXBElement<T>(elementQName, (Class<T>) jaxbObject.getClass(), jaxbObject);
        marshalElementToDom(jaxbElement, parentElement);
    }

    public Element toDomElement(Object element) throws JAXBException {
        return toDomElement(element, DOMUtil.getDocument());
    }

    public Element toDomElement(Object jaxbElement, Document doc) throws JAXBException {
        return toDomElement(jaxbElement, doc, false, false, false);
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Element toDomElement(Object jaxbElement, Document doc, boolean adopt, boolean clone, boolean deep)
            throws JAXBException {
        if (jaxbElement == null) {
            return null;
        }
        if (jaxbElement instanceof Element) {
            Element domElement = (Element) jaxbElement;
            if (clone) {
                domElement = (Element) domElement.cloneNode(deep);
            }
            if (domElement.getOwnerDocument().equals(doc)) {
                return domElement;
            }
            if (adopt) {
                doc.adoptNode(domElement);
            }
            return domElement;
        } else if (jaxbElement instanceof JAXBElement) {
            return marshalElementToDom((JAXBElement) jaxbElement, doc);
        } else {
            throw new IllegalArgumentException(
                    "Not an element: " + jaxbElement + " (" + jaxbElement.getClass().getName() + ")");
        }
    }

    public <T> JAXBElement<T> unmarshalElement(String xmlString, Class<T> type)
            throws JAXBException, SchemaException {
        if (xmlString == null) {
            return null;
        }

        xmlString = xmlString.trim();
        if (!xmlString.startsWith("<") || !xmlString.endsWith(">")) {
            throw new IllegalArgumentException("Provided string is unlikely to be an XML");
        }

        StringReader reader = null;
        try {
            reader = new StringReader(xmlString);
            JAXBElement<T> element = unmarshalElement(reader, type);
            adopt(element);
            return element;
        } finally {
            if (reader != null) {
                IOUtils.closeQuietly(reader);
            }
        }
    }

    public <T> T unmarshalObject(InputStream input, Class<T> type) throws JAXBException, SchemaException {
        Object object = getUnmarshaller().unmarshal(input);
        JAXBElement<T> jaxbElement = (JAXBElement<T>) object;
        adopt(jaxbElement);

        if (jaxbElement == null) {
            return null;
        }
        T value = jaxbElement.getValue();
        // adopt not needed, already adopted in unmarshalElement call above
        return value;

    }

    public <T> T unmarshalObject(InputStream input) throws JAXBException, SchemaException {
        Object object = getUnmarshaller().unmarshal(input);
        JAXBElement<T> jaxbElement = (JAXBElement<T>) object;
        adopt(jaxbElement);

        if (jaxbElement == null) {
            return null;
        }
        T value = jaxbElement.getValue();
        // adopt not needed, already adopted in unmarshalElement call above
        return value;

    }

    public <T> JAXBElement<T> unmarshalElement(Reader reader, Class<T> type) throws JAXBException, SchemaException {
        Object object = getUnmarshaller().unmarshal(reader);
        JAXBElement<T> jaxbElement = (JAXBElement<T>) object;
        adopt(jaxbElement);
        return jaxbElement;
    }

    public <T> T unmarshalToObject(Node node, Class<T> type) throws JAXBException, SchemaException {
        JAXBElement<T> element = unmarshalElement(node, type);
        if (element == null) {
            return null;
        }
        adopt(element);
        return element.getValue();
    }

    public <T> JAXBElement<T> unmarshalElement(Node node, Class<T> type) throws JAXBException, SchemaException {
        Object object = createUnmarshaller().unmarshal(node);
        JAXBElement<T> jaxbElement = (JAXBElement<T>) object;
        adopt(jaxbElement);
        return jaxbElement;
    }

    public <T> T unmarshalObject(File file, Class<T> type)
            throws JAXBException, SchemaException, FileNotFoundException {
        JAXBElement<T> element = unmarshalElement(file, type);
        if (element == null) {
            return null;
        }
        T value = element.getValue();
        // adopt not needed, already adopted in unmarshalElement call above
        if (!type.isAssignableFrom(value.getClass())) {
            throw new IllegalArgumentException(
                    "Unmarshalled " + value.getClass() + " from file " + file + " while " + type + " was expected");
        }
        return value;
    }

    public Object unmarshalObjects(File file) throws JAXBException {
        return createUnmarshaller().unmarshal(file);
    }

    public <T> T unmarshalObject(String stringXml, Class<T> type) throws JAXBException, SchemaException {
        JAXBElement<T> element = unmarshalElement(stringXml, type);
        if (element == null) {
            return null;
        }
        T value = element.getValue();
        adopt(value, type);
        return value;
    }

    // element name must correspond to the name that points to the container definition
    public <T extends Containerable> PrismContainer<T> unmarshalSingleValueContainer(File file, Class<T> type)
            throws JAXBException, SchemaException, FileNotFoundException {
        return unmarshalSingleValueContainer(unmarshalElement(file, type));
    }

    // element name must correspond to the name that points to the container definition
    public <T extends Containerable> PrismContainer<T> unmarshalSingleValueContainer(String stringXml,
            Class<T> type) throws JAXBException, SchemaException {
        return unmarshalSingleValueContainer(unmarshalElement(stringXml, type));
    }

    // element name must correspond to the name that points to the container definition
    private <T extends Containerable> PrismContainer<T> unmarshalSingleValueContainer(JAXBElement<T> element)
            throws JAXBException, SchemaException {
        if (element == null) {
            return null;
        }
        T value = element.getValue();

        // this is a bit tricky - we have to create a container and put the newly obtained value into it
        PrismContainerValue<T> containerValue = value.asPrismContainerValue();
        containerValue.revive(prismContext);
        PrismContainerDefinition definition = prismContext.getSchemaRegistry()
                .findContainerDefinitionByElementName(element.getName());
        if (definition == null) {
            throw new IllegalStateException(
                    "There's no container definition for element name " + element.getName());
        }
        containerValue.applyDefinition(definition, false);
        PrismContainer container = definition.instantiate();
        container.add(containerValue);
        return container;
    }

    public <T> T unmarshalObject(Object domOrJaxbElement, Class<T> type) throws SchemaException {
        JAXBElement<T> element;
        if (domOrJaxbElement instanceof JAXBElement<?>) {
            element = (JAXBElement<T>) domOrJaxbElement;
        } else if (domOrJaxbElement instanceof Node) {
            try {
                element = unmarshalElement((Node) domOrJaxbElement, type);
            } catch (JAXBException e) {
                throw new SchemaException(e.getMessage(), e);
            }
        } else {
            throw new IllegalArgumentException("Unknown element type " + domOrJaxbElement);
        }
        if (element == null) {
            return null;
        }
        T value = element.getValue();
        adopt(value, type);
        return value;
    }

    public <T> JAXBElement<T> unmarshalElement(File file, Class<T> type)
            throws SchemaException, FileNotFoundException, JAXBException {
        if (file == null) {
            throw new IllegalArgumentException("File argument must not be null.");
        }

        InputStream is = null;
        try {
            is = new FileInputStream(file);
            JAXBElement<T> element = (JAXBElement<T>) getUnmarshaller().unmarshal(is);
            adopt(element);
            return element;
        } catch (RuntimeException ex) {
            throw new SystemException(ex);
        } finally {
            if (is != null) {
                IOUtils.closeQuietly(is);
            }
        }
    }

    public <T> JAXBElement<T> unmarshalElement(InputStream is, Class<T> type)
            throws SchemaException, FileNotFoundException, JAXBException {

        try {
            JAXBElement<T> element = (JAXBElement<T>) getUnmarshaller().unmarshal(is);
            adopt(element);
            return element;
        } finally {
            if (is != null) {
                IOUtils.closeQuietly(is);
            }
        }
    }

    public <T> T unmarshalRootObject(File file, Class<T> type)
            throws JAXBException, FileNotFoundException, SchemaException {
        Validate.notNull(file, "File must not be null.");
        InputStream is = null;
        try {
            is = new FileInputStream(file);
            T object = (T) getUnmarshaller().unmarshal(is);
            adopt(object);
            return object;
        } finally {
            if (is != null) {
                IOUtils.closeQuietly(is);
            }
        }
    }

    public boolean compareAny(List<Object> a, List<Object> b) {
        if (a == b) {
            return true;
        }
        if (a == null && b == null) {
            return true;
        }
        if (a == null || b == null) {
            return false;
        }
        if (a.size() != b.size()) {
            return false;
        }
        for (int i = 0; i < a.size(); i++) {
            if (!compareElement(a.get(i), b.get(i))) {
                return false;
            }
        }
        return true;
    }

    @SuppressWarnings("unchecked")
    private boolean compareElement(Object a, Object b) {
        if (a == b) {
            return true;
        }
        if (a == null && b == null) {
            return true;
        }
        if (a == null || b == null) {
            return false;
        }
        Document doc = null;
        Element ae = null;
        Element be = null;

        if (a instanceof Element) {
            ae = (Element) a;
        } else if (a instanceof JAXBElement) {
            if (doc == null) {
                doc = DOMUtil.getDocument();
            }
            try {
                ae = marshalElementToDom((JAXBElement) a, doc);
            } catch (JAXBException e) {
                throw new IllegalStateException("Failed to marshall element " + a, e);
            }
        } else {
            throw new IllegalArgumentException("Got unexpected type " + a.getClass().getName() + ": " + a);
        }

        if (b instanceof Element) {
            be = (Element) b;
        } else if (a instanceof JAXBElement) {
            if (doc == null) {
                doc = DOMUtil.getDocument();
            }
            try {
                be = marshalElementToDom((JAXBElement) a, doc);
            } catch (JAXBException e) {
                throw new IllegalStateException("Failed to marshall element " + b, e);
            }
        } else {
            throw new IllegalArgumentException("Got unexpected type " + b.getClass().getName() + ": " + b);
        }

        return DOMUtil.compareElement(ae, be, true);
    }

    public <T> T fromElement(Object element, Class<T> type) throws SchemaException {

        if (element == null) {
            return null;
        }

        if (type.isAssignableFrom(element.getClass())) {
            return (T) element;
        }

        if (element instanceof JAXBElement) {
            if (((JAXBElement) element).getValue() == null) {
                return null;
            }
            if (type.isAssignableFrom(((JAXBElement) element).getValue().getClass())) {
                return (T) ((JAXBElement) element).getValue();
            }
        }

        if (element instanceof Element) {
            try {
                JAXBElement<T> unmarshalledElement = unmarshalElement((Element) element, type);
                return unmarshalledElement.getValue();
            } catch (JAXBException e) {
                throw new IllegalArgumentException("Unmarshall failed: " + e.getMessage(), e);
            }
        }

        throw new IllegalArgumentException("Unknown element type " + element.getClass().getName());
    }

    private QName determineElementQName(Objectable objectable) {
        PrismObject<?> prismObject = objectable.asPrismObject();
        if (prismObject.getElementName() != null) {
            return prismObject.getElementName();
        }
        PrismObjectDefinition<?> definition = prismObject.getDefinition();
        if (definition != null) {
            if (definition.getName() != null) {
                return definition.getName();
            }
        }
        throw new IllegalStateException("Cannot determine element name of " + objectable);
    }

    private QName determineElementQName(Containerable containerable) {
        PrismContainerValue prismContainerValue = containerable.asPrismContainerValue();
        PrismContainerDefinition<?> definition = prismContainerValue.getParent() != null
                ? prismContainerValue.getParent().getDefinition()
                : null;
        if (definition != null) {
            if (definition.getName() != null) {
                return definition.getName();
            }
        }
        throw new IllegalStateException("Cannot determine element name of " + containerable + " (parent = "
                + prismContainerValue.getParent() + ", definition = " + definition + ")");
    }

    private boolean isObjectable(Class type) {
        return Objectable.class.isAssignableFrom(type);
    }

    private <T> void adopt(T object, Class<T> type) throws SchemaException {
        if (object instanceof Objectable) {
            getPrismContext().adopt(((Objectable) object));
        }
    }

    private void adopt(Object object) throws SchemaException {
        if (object instanceof JAXBElement) {
            adopt(((JAXBElement) object).getValue());
        } else if (object instanceof Objectable) {
            getPrismContext().adopt(((Objectable) (object)));
        }
    }

    public static String marshalWrap(Object jaxbObject) throws JAXBException {
        JAXBElement<Object> jaxbElement = new JAXBElement<Object>(DEFAULT_ELEMENT_NAME,
                (Class) jaxbObject.getClass(), jaxbObject);
        return getInstance().marshalElementToString(jaxbElement);
    }

}