Package org.apache.tuscany.core.implementation.processor

Source Code of org.apache.tuscany.core.implementation.processor.ImplementationProcessorServiceImpl

/*
* 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.tuscany.core.implementation.processor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Member;
import java.util.List;
import javax.xml.namespace.QName;

import org.osoa.sca.annotations.Callback;
import org.osoa.sca.annotations.Property;
import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Remotable;

import org.apache.tuscany.spi.annotation.Autowire;
import org.apache.tuscany.spi.idl.InvalidServiceContractException;
import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry;
import org.apache.tuscany.spi.idl.java.JavaServiceContract;
import org.apache.tuscany.spi.implementation.java.DuplicatePropertyException;
import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService;
import org.apache.tuscany.spi.implementation.java.JavaMappedProperty;
import org.apache.tuscany.spi.implementation.java.JavaMappedReference;
import org.apache.tuscany.spi.implementation.java.JavaMappedService;
import org.apache.tuscany.spi.implementation.java.PojoComponentType;
import org.apache.tuscany.spi.implementation.java.ProcessingException;
import org.apache.tuscany.spi.model.OverrideOptions;
import org.apache.tuscany.spi.model.ServiceContract;

import org.apache.tuscany.core.idl.java.IllegalCallbackException;
import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName;

/**
* The default implementation of an <code>ImplementationProcessorService</code>
*
* @version $Rev: 453797 $ $Date: 2006-10-06 15:35:33 -0700 (Fri, 06 Oct 2006) $
*/
public class ImplementationProcessorServiceImpl implements ImplementationProcessorService {
    private JavaInterfaceProcessorRegistry registry;

    public ImplementationProcessorServiceImpl(@Autowire JavaInterfaceProcessorRegistry registry) {
        this.registry = registry;
    }

    public JavaMappedService createService(Class<?> interfaze) throws InvalidServiceContractException {
        JavaMappedService service = new JavaMappedService();
        service.setName(getBaseName(interfaze));
        service.setRemotable(interfaze.getAnnotation(Remotable.class) != null);
        ServiceContract<?> contract = registry.introspect(interfaze);
        service.setServiceContract(contract);
        return service;
    }

    public void processCallback(Class<?> interfaze, ServiceContract<?> contract) throws IllegalCallbackException {
        Callback callback = interfaze.getAnnotation(Callback.class);
        if (callback != null && !Void.class.equals(callback.value())) {
            Class<?> callbackClass = callback.value();
            contract.setCallbackClass(callbackClass);
            contract.setCallbackName(getBaseName(callbackClass));
        } else if (callback != null && Void.class.equals(callback.value())) {
            IllegalCallbackException e = new IllegalCallbackException(
                "Callback annotation must specify an interface on service type");
            e.setIdentifier(interfaze.getName());
            throw e;
        }
    }

    public boolean areUnique(Class[] collection) {
        if (collection.length == 0) {
            return true;
        }
        return areUnique(collection, 0);
    }

    public void addName(List<String> names, int pos, String name) {
        if (names.size() < pos) {
            for (int i = 0; i < pos; i++) {
                names.add(i, "");
            }
            names.add(name);
        } else if (names.size() > pos) {
            names.remove(pos);
            names.add(pos, name);
        } else {
            names.add(pos, name);
        }
    }

    public boolean processParam(
        Class<?> param,
        Annotation[] paramAnnotations,
        String[] constructorNames,
        int pos,
        PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
        List<String> injectionNames) throws ProcessingException {
        boolean processed = false;
        for (Annotation annot : paramAnnotations) {
            if (Autowire.class.equals(annot.annotationType())) {
                processed = true;
                processAutowire(annot, constructorNames, pos, param, type, injectionNames);
            } else if (Property.class.equals(annot.annotationType())) {
                processed = true;
                processProperty(annot, constructorNames, pos, type, param, injectionNames);
            } else if (Reference.class.equals(annot.annotationType())) {
                processed = true;
                processReference(annot, constructorNames, pos, type, param, injectionNames);
            }
        }
        return processed;
    }

    public boolean injectionAnnotationsPresent(Annotation[][] annots) {
        for (Annotation[] annotations : annots) {
            for (Annotation annotation : annotations) {
                Class<? extends Annotation> annotType = annotation.annotationType();
                if (annotType.equals(Autowire.class) || annotType.equals(Property.class)
                    || annotType.equals(Reference.class)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Determines if all the members of a collection have unique types
     *
     * @param collection the collection to analyze
     * @param start      the position in the collection to start
     * @return true if the types are unique
     */
    private boolean areUnique(Class[] collection, int start) {
        Object compare = collection[start];
        for (int i = start + 1; i < collection.length; i++) {
            if (compare.equals(collection[i])) {
                return false;
            }
        }
        if (start + 1 < collection.length) {
            return areUnique(collection, start + 1);
        } else {
            return true;
        }
    }

    /**
     * Processes autowire metadata for a constructor parameter
     *
     * @param annot            the autowire annotation
     * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor}
     *                         annotation
     * @param pos              the position of the parameter in the constructor's parameter list
     * @param param            the parameter type
     * @param type             the component type associated with the implementation being processed
     * @param injectionNames   the collection of injection names to update
     * @throws InvalidAutowireException
     * @throws InvalidConstructorException
     */
    private void processAutowire(
        Annotation annot,
        String[] constructorNames,
        int pos,
        Class<?> param,
        PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
        List<String> injectionNames) throws InvalidAutowireException, InvalidConstructorException {
        // the param is marked as an autowire
        Autowire autowireAnnot = (Autowire) annot;
        JavaMappedReference reference = new JavaMappedReference();
        reference.setAutowire(true);
        String name = autowireAnnot.name();
        if (name == null || name.length() == 0) {
            if (constructorNames.length > 1 && (constructorNames.length < pos + 1 || constructorNames[pos] == null)) {
                throw new InvalidAutowireException("Names in @Constructor and autowire parameter do not match at "
                    + (pos + 1));
            } else if (constructorNames.length == 1 && constructorNames[0].length() == 0) {
                // special case when @Constructor present with all autowire params not specifying any name
                name = param.getName() + String.valueOf(pos);
            } else if (constructorNames.length == 1
                && (constructorNames.length < pos + 1 || constructorNames[pos] == null)) {
                throw new InvalidAutowireException("Names in @Constructor and autowire parameter do not match at "
                    + (pos + 1));
            } else if (constructorNames.length == 1 && constructorNames[0].length() > 0) {
                name = constructorNames[pos];
            } else if (constructorNames.length == 0 || constructorNames[pos].length() == 0) {
                name = param.getName() + String.valueOf(pos);
            } else {
                name = constructorNames[pos];
            }
        } else if (pos < constructorNames.length && constructorNames[pos] != null
            && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) {
            throw new InvalidConstructorException("Name specified by @Constructor does not match autowire name at "
                + (pos + 1));
        }
        reference.setName(name);

        reference.setRequired(autowireAnnot.required());

        ServiceContract<?> contract = new JavaServiceContract();
        contract.setInterfaceClass(param);
        reference.setServiceContract(contract);
        type.getReferences().put(name, reference);
        addName(injectionNames, pos, name);
    }

    /**
     * Processes parameter metadata for a constructor parameter
     *
     * @param annot            the parameter annotation
     * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor}
     *                         annotation
     * @param pos              the position of the parameter in the constructor's parameter list
     * @param type             the component type associated with the implementation being processed
     * @param param            the parameter type
     * @param explicitNames    the collection of injection names to update
     * @throws ProcessingException
     */
    private <T> void processProperty(
        Annotation annot,
        String[] constructorNames,
        int pos,
        PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
        Class<T> param,
        List<String> explicitNames) throws ProcessingException {
        // TODO multiplicity
        // the param is marked as a property
        Property propAnnot = (Property) annot;
        JavaMappedProperty<T> property = new JavaMappedProperty<T>();
        String name = propAnnot.name();
        if (name == null || name.length() == 0) {
            if (constructorNames.length < pos + 1 || constructorNames[pos] == null
                || constructorNames[pos].length() == 0) {
                throw new InvalidPropertyException("No name specified for property parameter " + (pos + 1));
            }
            name = constructorNames[pos];
        } else if (pos < constructorNames.length && constructorNames[pos] != null
            && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) {
            throw new InvalidConstructorException("Name specified by @Constructor does not match property name at "
                + (pos + 1));
        }
        if (type.getProperties().get(name) != null) {
            throw new DuplicatePropertyException(name);
        }
        property.setName(name);
        property.setOverride(OverrideOptions.valueOf(propAnnot.override().toUpperCase()));

        property.setXmlType(QName.valueOf(propAnnot.xmlType()));
        property.setJavaType(param);
        type.getProperties().put(name, property);
        addName(explicitNames, pos, name);
    }

    /**
     * Processes reference metadata for a constructor parameter
     *
     * @param annot            the parameter annotation
     * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor}
     *                         annotation
     * @param pos              the position of the parameter in the constructor's parameter list
     * @param type             the component type associated with the implementation being processed
     * @param param            the parameter type
     * @param explicitNames    the collection of injection names to update
     * @throws ProcessingException
     */
    private void processReference(
        Annotation annot,
        String[] constructorNames,
        int pos,
        PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type,
        Class<?> param,
        List<String> explicitNames) throws ProcessingException {

        // TODO multiplicity
        // the param is marked as a reference
        Reference refAnnotation = (Reference) annot;
        JavaMappedReference reference = new JavaMappedReference();
        String name = refAnnotation.name();
        if (name == null || name.length() == 0) {
            if (constructorNames.length < pos + 1 || constructorNames[pos] == null
                || constructorNames[pos].length() == 0) {
                throw new InvalidReferenceException("No name specified for reference parameter " + (pos + 1));
            }
            name = constructorNames[pos];
        } else if (pos < constructorNames.length && constructorNames[pos] != null
            && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) {
            throw new InvalidConstructorException("Name specified by @Constructor does not match reference name at "
                + (pos + 1));
        }
        if (type.getReferences().get(name) != null) {
            throw new DuplicateReferenceException(name);
        }
        reference.setName(name);
        reference.setRequired(refAnnotation.required());
        try {
            ServiceContract<?> contract = registry.introspect(param);
            reference.setServiceContract(contract);
        } catch (InvalidServiceContractException e) {
            throw new ProcessingException(e);
        }
        type.getReferences().put(name, reference);
        addName(explicitNames, pos, name);
    }

    public JavaMappedReference createReference(String name, Member member, Class<?> paramType)
        throws ProcessingException {
        JavaMappedReference reference = new JavaMappedReference();
        reference.setName(name);
        reference.setMember(member);
        reference.setRequired(false);
        ServiceContract contract = null;
        try {
            contract = registry.introspect(paramType);
        } catch (InvalidServiceContractException e1) {
            throw new ProcessingException(e1);
        }
        try {
            processCallback(paramType, contract);
        } catch (IllegalCallbackException e) {
            throw new ProcessingException(e);
        }
        reference.setServiceContract(contract);
        return reference;
    }

}
TOP

Related Classes of org.apache.tuscany.core.implementation.processor.ImplementationProcessorServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.