Package org.apache.tuscany.sca.databinding

Source Code of org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint$LazyDataBinding

/*
* 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.sca.databinding;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.tuscany.sca.contribution.util.ServiceDeclaration;
import org.apache.tuscany.sca.contribution.util.ServiceDiscovery;
import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding;
import org.apache.tuscany.sca.databinding.javabeans.JavaExceptionDataBinding;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;

/**
* The default implementation of a data binding extension point.
*
* @version $Rev: 608514 $ $Date: 2008-01-03 15:01:00 +0000 (Thu, 03 Jan 2008) $
*/
public class DefaultDataBindingExtensionPoint implements DataBindingExtensionPoint {
    private final Map<String, DataBinding> bindings = new HashMap<String, DataBinding>();
    private final List<DataBinding> databindings = new ArrayList<DataBinding>();
    private static final Logger logger = Logger.getLogger(DefaultDataBindingExtensionPoint.class.getName());
    private boolean loadedDataBindings;

    public DefaultDataBindingExtensionPoint() {
    }

    public DataBinding getDataBinding(String id) {
        if (id == null) {
            return null;
        }
        DataBinding dataBinding = bindings.get(id.toLowerCase());
        if (dataBinding == null) {
            loadDataBindings();
            dataBinding = bindings.get(id.toLowerCase());
        }
        return dataBinding;
    }

    public void addDataBinding(DataBinding dataBinding) {
      if (logger.isLoggable(Level.FINE)) {
      String className = dataBinding.getClass().getName();
      boolean lazy = false;
      if (dataBinding instanceof LazyDataBinding) {
        className = ((LazyDataBinding) dataBinding).dataBindingDeclaration.getClassName();
        lazy = true;
      }
      logger.fine("Adding databinding: " + className + ";type="
          + dataBinding.getName() + ",lazy=" + lazy);
    }
        databindings.add(dataBinding);
    bindings.put(dataBinding.getName().toLowerCase(), dataBinding);

        String[] aliases = dataBinding.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                bindings.put(alias.toLowerCase(), dataBinding);
            }
        }
    }

    public DataBinding removeDataBinding(String id) {
        if (id == null) {
            return null;
        }
        DataBinding dataBinding = bindings.remove(id.toLowerCase());
        if (dataBinding != null) {
            databindings.remove(dataBinding);
            String[] aliases = dataBinding.getAliases();
            if (aliases != null) {
                for (String alias : aliases) {
                    bindings.remove(alias.toLowerCase());
                }
            }
        }
        return dataBinding;
    }

    /**
     * Dynamically load data bindings declared under META-INF/services
     */
    private void loadDataBindings() {
        if (loadedDataBindings)
            return;

        // Get the databinding service declarations
        Set<ServiceDeclaration> dataBindingDeclarations;
        try {
            dataBindingDeclarations =
                ServiceDiscovery.getInstance().getServiceDeclarations(DataBinding.class);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        // Load data bindings
        for (ServiceDeclaration dataBindingDeclaration : dataBindingDeclarations) {
            Map<String, String> attributes = dataBindingDeclaration.getAttributes();
            String type = attributes.get("type");
            String name = attributes.get("name");

            // Create a data binding wrapper and register it
            DataBinding dataBinding = new LazyDataBinding(type, name, dataBindingDeclaration);
            addDataBinding(dataBinding);
        }

        loadedDataBindings = true;
    }

    /**
     * A data binding facade allowing data bindings to be lazily loaded and
     * initialized.
     */
    private static class LazyDataBinding implements DataBinding {

        private String name;
        private String[] aliases;
        private ServiceDeclaration dataBindingDeclaration;
        private DataBinding dataBinding;

        private LazyDataBinding(String type, String name, ServiceDeclaration dataBindingDeclaration) {
            this.name = type;
            if (name != null) {
                this.aliases = new String[] {name};
            }
            this.dataBindingDeclaration = dataBindingDeclaration;
        }

        /**
         * Load and instantiate the data binding class.
         *
         * @return The data binding.
         */
        @SuppressWarnings("unchecked")
        private DataBinding getDataBinding() {
            if (dataBinding == null) {
                try {
                    Class<DataBinding> dataBindingClass =
                        (Class<DataBinding>)dataBindingDeclaration.loadClass();
                    Constructor<DataBinding> constructor = dataBindingClass.getConstructor();
                    dataBinding = constructor.newInstance();
                } catch (Exception e) {
                    throw new IllegalStateException(e);
                }
            }
            return dataBinding;
        }

        public Object copy(Object object) {
            return getDataBinding().copy(object);
        }

        public String[] getAliases() {
            return aliases;
        }

        public ExceptionHandler getExceptionHandler() {
            return getDataBinding().getExceptionHandler();
        }

        public String getName() {
            return name;
        }

        public SimpleTypeMapper getSimpleTypeMapper() {
            return getDataBinding().getSimpleTypeMapper();
        }

        public WrapperHandler getWrapperHandler() {
            return getDataBinding().getWrapperHandler();
        }

        public boolean introspect(DataType dataType, Annotation[] annotations) {
            return getDataBinding().introspect(dataType, annotations);
        }

        public DataType introspect(Object value) {
            return getDataBinding().introspect(value);
        }
    }

    //FIXME The following methods should not be on the extension point
    // they should be on a separate class
    public boolean introspectType(DataType dataType, Annotation[] annotations) {
        return introspectType(dataType, annotations, false);
    }

    private boolean introspectArray(DataType dataType, Annotation[] annotations) {
        Class physical = dataType.getPhysical();
        if (!physical.isArray() || physical == byte[].class) {
            return false;
        }
        Class componentType = physical.getComponentType();
        DataType logical = new DataTypeImpl(componentType, dataType.getLogical());
        introspectType(logical, annotations);
        dataType.setDataBinding("java:array");
        dataType.setLogical(logical);
        return true;
    }

    //
    // Leverage the DataBinding ExceptionHandler to calculate the DataType of an exception DataType
    //
    public boolean introspectType(DataType dataType, Annotation[] annotations, boolean isException) {
        loadDataBindings();
        for (DataBinding binding : databindings) {
            // don't introspect for JavaBeansDatabinding as all javatypes will
            // anyways match to its basetype
            // which is java.lang.Object. Default to this only if no databinding
            // results
            if (!binding.getName().equals(JavaBeansDataBinding.NAME)) {
                if (isException) {
                    // Next look to see if the DB's exceptionHandler handles this exception
                    ExceptionHandler excHandler = binding.getExceptionHandler();
                    if (excHandler != null) {
                        // Assymetric to have the introspect() methods set the DataBindings themselves
                        // whereas we're setting it ourselves here.  
                        DataType faultType = excHandler.getFaultType(dataType);
                        if (faultType != null) {
                            dataType.setDataBinding(binding.getName());
                            dataType.setLogical(faultType);
                            return true;
                        }
                    }
                } else {
                    if (binding.introspect(dataType, annotations)) {
                        return true;
                    }
                }
            }
        }
        // FIXME: Should we honor the databinding from operation/interface
        // level?
        Class physical = dataType.getPhysical();
        if (physical == Object.class) {
            return false;
        }
        if (dataType.getPhysical().isArray()) {
            introspectArray(dataType, annotations);
            return true;
        } else if (isException) {
            dataType.setDataBinding(JavaExceptionDataBinding.NAME);
            return false;
        } else {
            dataType.setDataBinding(JavaBeansDataBinding.NAME);
            return false;
        }
    }

    public DataType introspectType(Object value) {
        loadDataBindings();
        DataType dataType = null;
        for (DataBinding binding : bindings.values()) {
            // don't introspect for JavaBeansDatabinding as all javatypes will
            // anyways match to its basetype
            // which is java.lang.Object. Default to this only if no databinding
            // results
            if (!binding.getName().equals(JavaBeansDataBinding.NAME)) {
                dataType = binding.introspect(value);
            }
            if (dataType != null) {
                return dataType;
            }
        }
        return new DataTypeImpl<Class>(JavaBeansDataBinding.NAME, value.getClass(), value.getClass());
    }
}
TOP

Related Classes of org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint$LazyDataBinding

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.