alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Apache CXF example source code file (StructType.java)

This example Apache CXF source code file (StructType.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Apache CXF tags/keywords

aegistype, aegistype, beantype, beantype, beantypeinfo, beantypeinfo, class, object, object, override, qname, soapref, structtype, writepropertyaction

The Apache CXF StructType.java source code

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 org.apache.cxf.aegis.type.encoded;

import javax.xml.namespace.QName;

import org.apache.cxf.aegis.Context;
import org.apache.cxf.aegis.DatabindingException;
import org.apache.cxf.aegis.type.AegisType;
import org.apache.cxf.aegis.type.basic.BeanType;
import org.apache.cxf.aegis.type.basic.BeanTypeInfo;
import org.apache.cxf.aegis.xml.MessageReader;
import org.apache.cxf.aegis.xml.MessageWriter;

/**
 * StructType is a small extension of the BeanType which can properly read and write SOAP encoded structs. The
 * modifications are:
 * <ul>
 * <li>Nested elements MUST be unqualified
 * <li>Nested elements MAY contain a SOAP ref attribute instead of an inline value
 * <li>Struct MAY contain a SOAP id attribute
 * </ul>
 * </p>
 * When writting, the class will always write the struct in the following canonical format:
 * <ul>
 * <li>Struct will contain a SOAP id
 * <li>Nested structs will be written as SOAP references (with SoapRefType)
 * </ul>
 */
public class StructType extends BeanType {
    public StructType() {
    }

    public StructType(BeanTypeInfo info) {
        super(info);
    }
    
    //soap-encoding always allow xsi:nil=true to be set
    protected boolean alwaysAllowNillables() {
        return true;
    }

    /**
     * Gets the BeanTypeInfo using an unqualified name.
     * @param name the unqualified name of the element
     * @return the BeanTypeInfo containing a property with the specified unqualified name
     */
    @Override
    protected BeanTypeInfo getBeanTypeInfoWithProperty(QName name) {
        // nested elements use unqualified names
        name = qualifyName(name);

        return super.getBeanTypeInfoWithProperty(name);
    }

    /**
     * Returns a SoapRefType wrapping the actual type.
     */
    @Override
    protected AegisType getElementType(QName name,
            BeanTypeInfo beanTypeInfo,
            MessageReader reader,
            Context context) {
        
        // nested elements use unqualified names
        name = qualifyName(name);

        AegisType type = super.getElementType(name, beanTypeInfo, reader, context);
        if (type != null) {
            type = new SoapRefType(type);
        }
        return type;
    }

    /**
     * Adds special handeling for SoapRefs
     */
    @Override
    protected void writeProperty(QName name,
            Object object,
            Object property,
            Class impl,
            BeanTypeInfo inf) throws DatabindingException {

        // nested elements use unqualified names
        name = qualifyName(name);

        if (property instanceof SoapRef) {
            SoapRef soapRef = (SoapRef) property;

            // register an action with the ref that will set the bean property
            // if the reference has already been resolved the action will be
            // invoked immedately
            soapRef.setAction(new WritePropertyAction(name, object, impl, inf));
        } else {
            // normal property
            super.writeProperty(name, object, property, impl, inf);
        }
    }

    /**
     * Writes a nested element with an unqualified name.
     */
    @Override
    protected void writeElement(QName name, Object value, 
                                AegisType type, MessageWriter writer, Context context) {
        // Nested elements are unqualified
        name = new QName("", name.getLocalPart());

        MessageWriter cwriter = writer.getElementWriter(name);

        if (type instanceof BeanType || type instanceof SoapArrayType) {
            String refId = MarshalRegistry.get(context).getInstanceId(value);
            SoapEncodingUtil.writeRef(cwriter, refId);
        } else {
            type.writeObject(value, cwriter, context);
        }

        cwriter.close();
    }

    /**
     * Gets the qualified name of a nested element.  Soap encoded structs contain unqualified elements so
     * the method searches for a property matching the local part of the unqualified name.
     */
    private QName qualifyName(QName name) {
        // is the name already qualified, we're done
        if (!"".equals(name.getNamespaceURI())) {
            return name;
        }

        // find the matching property and get it's name
        for (BeanType sooper = this; sooper != null; sooper = superBeanType(sooper)) {
            QName qualifiedName = new QName(sooper.getTypeInfo().getDefaultNamespace(), name.getLocalPart());

            if (sooper.getTypeInfo().getType(qualifiedName) != null) {
                return qualifiedName;
            }
        }

        return name;
    }
    
    private BeanType superBeanType(AegisType t) {
        if (t instanceof BeanType) {
            BeanType bt = (BeanType)t;
            AegisType supertype = bt.getSuperType();
            if (supertype instanceof BeanType) {
                return (BeanType)supertype;
            }
        }
        return null;
    }

    /**
     * When the SoapRef is resolved write the matching property on the target object.
     */
    private final class WritePropertyAction implements SoapRef.Action {
        private final QName name;
        private final Object targetObject;
        private final Class targetClass;
        private final BeanTypeInfo beanTypeInfo;

        private WritePropertyAction(QName name,
                Object targetObject,
                Class targetClass,
                BeanTypeInfo beanTypeInfo) {
            this.name = name;
            this.targetObject = targetObject;
            this.targetClass = targetClass;
            this.beanTypeInfo = beanTypeInfo;
        }

        public void onSet(SoapRef ref) {
            writeProperty(name, targetObject, ref.get(), targetClass, beanTypeInfo);
        }
    }
}

Other Apache CXF examples (source code examples)

Here is a short list of links related to this Apache CXF StructType.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.