com.microsoft.tfs.core.internal.wrappers.WrapperUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.tfs.core.internal.wrappers.WrapperUtils.java

Source

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See License.txt in the repository root.

package com.microsoft.tfs.core.internal.wrappers;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.text.MessageFormat;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Item;
import com.microsoft.tfs.util.Check;

import ms.tfs.versioncontrol.clientservices._03._Item;

/**
 * <p>
 * Static utility methods for wrapping and unwrapping arrays of web service
 * objects with {@link WebServiceObjectWrapper}s. The work is done using
 * reflection, see the methods' Javadoc for details.
 * </p>
 * <p>
 * No methods are provided for wrapping/unwrapping single items, since this is
 * easily done via the constructor for the wrapper that takes the item, and the
 * wrapper's getWebServiceObject() method.
 * </p>
 *
 * @threadsafety thread-safe
 */
public abstract class WrapperUtils {
    private static final Log log = LogFactory.getLog(WrapperUtils.class);

    public static final String UNWRAP_METHOD_NAME = "getWebServiceObject"; //$NON-NLS-1$

    /**
     * <p>
     * Takes an array of web service objects (for example, an array of
     * {@link _Item}) and returns an array of web service wrapper objects of the
     * given type (for instance, {@link Item}).
     * </p>
     * <p>
     * A constructor for the given wrapper type that accepts one of the given
     * service objects must exist.
     * </p>
     * <p>
     * <code>null</code> values in the web service objects are copied into the
     * returned array.
     * </p>
     *
     * @param wrapperType
     *        the wrapper object class name (not array class) to use (must not
     *        be <code>null</code>)
     * @param webServiceObjects
     *        the objects to wrap (if null, null is returned)
     * @return a new array of wrapper objects, where each wraps one of the given
     *         web service objects
     */
    public static Object wrap(final Class wrapperType, final Object[] webServiceObjects) {
        Check.notNull(wrapperType, "wrapperType"); //$NON-NLS-1$

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

        final Object ret = Array.newInstance(wrapperType, webServiceObjects.length);
        Class webServiceObjectType = null;
        Constructor constructor = null;

        if (webServiceObjects.length > 0) {
            try {

                for (int i = 0; i < webServiceObjects.length; i++) {
                    if (constructor == null && webServiceObjects[i] != null) {
                        webServiceObjectType = webServiceObjects[i].getClass();
                        constructor = wrapperType.getConstructor(new Class[] { webServiceObjectType });
                    }

                    /*
                     * Persist null values.
                     */
                    Array.set(ret, i,
                            (webServiceObjects[i] != null)
                                    ? constructor.newInstance(new Object[] { webServiceObjects[i] })
                                    : null);
                }

            } catch (final NoSuchMethodException e) {
                final String message = MessageFormat.format(
                        "Wrapper error: the desired wrapper class {0} does not have a visible constructor that accepts the web service type {1}", //$NON-NLS-1$
                        wrapperType, webServiceObjectType);

                log.error(message, e);
                throw new RuntimeException(message);
            } catch (final Exception e) {
                final String message = MessageFormat.format("Error wrapping {0} in {1}", //$NON-NLS-1$
                        webServiceObjectType, wrapperType);

                log.error(message, e);
                throw new RuntimeException(message, e);
            }
        }

        return ret;
    }

    /**
     * <p>
     * Takes an array of web service wrapper (for example, an array of
     * {@link Item}) and returns an array of the wrapped web service objects
     * that were inside the given type (for instance, {@link _Item}).
     * </p>
     * <p>
     * A public method named {@link #UNWRAP_METHOD_NAME} which takes no
     * arguments and returns the wrapped web service object must exist.
     * </p>
     * <p>
     * <code>null</code> values in the wrapper objects will be persisted in the
     * returned array.
     * </p>
     *
     * @param webServiceObjectType
     *        the type of the wrapped web service object (not array type) (not
     *        null)
     * @param wrapperObjects
     *        the wrapper objects to get the contents from(if null, null is
     *        returned)
     * @return a new array of web service objects, each extracted from the given
     *         wrapper objects
     */
    public static Object unwrap(final Class webServiceObjectType, final Object[] wrapperObjects) {
        Check.notNull(webServiceObjectType, "webServiceObjectType"); //$NON-NLS-1$

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

        final Object ret = Array.newInstance(webServiceObjectType, wrapperObjects.length);
        if (wrapperObjects.length > 0) {
            try {
                Method method = null;
                for (int i = 0; i < wrapperObjects.length; i++) {
                    if (method == null && wrapperObjects[i] != null) {
                        method = wrapperObjects[i].getClass().getMethod(UNWRAP_METHOD_NAME, new Class[0]);
                    }

                    /*
                     * Persist null values.
                     */
                    Array.set(ret, i,
                            (wrapperObjects[i] != null) ? method.invoke(wrapperObjects[i], new Object[0]) : null);
                }

            } catch (final NoSuchMethodException e) {
                final String message = MessageFormat.format(
                        "Wrapper error: the given wrapper class {0} does not have a method named {1} that returns a {2}", //$NON-NLS-1$
                        wrapperObjects[0].getClass(), UNWRAP_METHOD_NAME, webServiceObjectType);

                log.error(message, e);
                throw new RuntimeException(message, e);
            } catch (final Exception e) {
                final String message = MessageFormat.format("Error unwrapping {0} from {1}", //$NON-NLS-1$
                        webServiceObjectType, wrapperObjects);

                log.error(message, e);
                throw new RuntimeException(message, e);
            }
        }
        return ret;
    }
}