All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.tuscany.sca.databinding.DefaultTransformerExtensionPoint Maven / Gradle / Ivy

The newest version!
/*
 * 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.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.databinding.impl.DirectedGraph;
import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
import org.apache.tuscany.sca.extensibility.ServiceDiscovery;

/**
 * @version $Rev: 830738 $ $Date: 2009-10-28 12:29:50 -0700 (Wed, 28 Oct 2009) $
 */
public class DefaultTransformerExtensionPoint implements TransformerExtensionPoint {
    private static final Logger logger = Logger.getLogger(DefaultTransformerExtensionPoint.class.getName());
    private boolean loadedTransformers;

    private ExtensionPointRegistry registry;
    private final DirectedGraph graph = new DirectedGraph();

    public DefaultTransformerExtensionPoint(ExtensionPointRegistry registry) {
        this.registry = registry;
    }

    public void addTransformer(String sourceType, String resultType, int weight, Transformer transformer, boolean publicTransformer) {
        if (logger.isLoggable(Level.FINE)) {
            String className = transformer.getClass().getName();
            boolean lazy = false;
            boolean pull = (transformer instanceof PullTransformer);
            if (transformer instanceof LazyPullTransformer) {
                className = ((LazyPullTransformer)transformer).transformerDeclaration.getClassName();
                lazy = true;
            }
            if (transformer instanceof LazyPushTransformer) {
                className = ((LazyPushTransformer)transformer).transformerDeclaration.getClassName();
                lazy = true;
            }

            logger.fine("Adding transformer: " + className
                + ";source="
                + sourceType
                + ",target="
                + resultType
                + ",weight="
                + weight
                + ",type="
                + (pull ? "pull" : "push")
                + ",lazy="
                + lazy);
        }
        graph.addEdge(sourceType, resultType, transformer, weight, publicTransformer);
    }

    public void addTransformer(Transformer transformer, boolean publicTransformer) {
        addTransformer(transformer.getSourceDataBinding(),
                       transformer.getTargetDataBinding(),
                       transformer.getWeight(),
                       transformer, publicTransformer);
    }

    public boolean removeTransformer(String sourceType, String resultType) {
        return graph.removeEdge(sourceType, resultType);
    }

    public Transformer getTransformer(String sourceType, String resultType) {
        loadTransformers();

        DirectedGraph.Edge edge = graph.getEdge(sourceType, resultType);
        return (edge == null) ? null : edge.getValue();
    }

    /**
     * Dynamically load transformers registered under META-INF/services.
     *
     */
    private synchronized void loadTransformers() {
        if (loadedTransformers) {
            return;
        }
        loadedTransformers = true;
        loadTransformers(PullTransformer.class);
        loadTransformers(PushTransformer.class);

    }

    /**
     * Dynamically load transformers registered under META-INF/services.
     *
     * @param transformerClass
     */
    private synchronized void loadTransformers(Class transformerClass) {

        // Get the transformer service declarations
        Collection transformerDeclarations;

        try {
            transformerDeclarations = registry.getServiceDiscovery().getServiceDeclarations(transformerClass.getName());

        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        // Load transformers
        for (ServiceDeclaration transformerDeclaration : transformerDeclarations) {
            Map attributes = transformerDeclaration.getAttributes();

            String source = attributes.get("source");
            String target = attributes.get("target");
            int weight = Integer.valueOf(attributes.get("weight"));
            String b = attributes.get("public");
            boolean pub = true;
            if (b != null) {
                pub = Boolean.valueOf(b);
            }

            // Create a transformer wrapper and register it
            Transformer transformer;
            if (transformerClass == PullTransformer.class) {
                transformer = new LazyPullTransformer(source, target, weight, transformerDeclaration);
            } else {
                transformer = new LazyPushTransformer(source, target, weight, transformerDeclaration);
            }
            addTransformer(transformer, pub);
        }
    }

    /**
     * A transformer facade allowing transformers to be lazily loaded
     * and initialized.
     */
    private class LazyPullTransformer implements PullTransformer {

        private String source;
        private String target;
        private int weight;
        private ServiceDeclaration transformerDeclaration;
        private PullTransformer transformer;

        public LazyPullTransformer(String source, String target, int weight, ServiceDeclaration transformerDeclaration) {
            this.source = source;
            this.target = target;
            this.weight = weight;
            this.transformerDeclaration = transformerDeclaration;
        }

        /**
         * Load and instantiate the transformer class.
         *
         * @return The transformer.
         */
        @SuppressWarnings("unchecked")
        private PullTransformer getTransformer() {
            if (transformer == null) {
                try {
                    Class> transformerClass =
                        (Class>)transformerDeclaration.loadClass();
                    try {
                        Constructor> constructor = transformerClass.getConstructor();
                        transformer = constructor.newInstance();
                    } catch (NoSuchMethodException e) {
                        Constructor> constructor =
                            transformerClass.getConstructor(ExtensionPointRegistry.class);
                        transformer = constructor.newInstance(registry);
                    }
                } catch (Exception e) {
                    throw new IllegalStateException(e);
                }
            }
            return transformer;
        }

        public String getSourceDataBinding() {
            return source;
        }

        public String getTargetDataBinding() {
            return target;
        }

        public int getWeight() {
            return weight;
        }

        public Object transform(Object source, TransformationContext context) {
            return getTransformer().transform(source, context);
        }

        @Override
        public String toString() {
            StringBuffer sb = new StringBuffer(super.toString());
            sb.append(";className=").append(transformerDeclaration.getClassName());
            return sb.toString();
        }
    }

    /**
     * A transformer facade allowing transformers to be lazily loaded
     * and initialized.
     */
    private class LazyPushTransformer implements PushTransformer {

        private String source;
        private String target;
        private int weight;
        private ServiceDeclaration transformerDeclaration;
        private PushTransformer transformer;

        public LazyPushTransformer(String source, String target, int weight, ServiceDeclaration transformerDeclaration) {
            this.source = source;
            this.target = target;
            this.weight = weight;
            this.transformerDeclaration = transformerDeclaration;
        }

        /**
         * Load and instantiate the transformer class.
         *
         * @return The transformer.
         */
        @SuppressWarnings("unchecked")
        private PushTransformer getTransformer() {
            if (transformer == null) {
                try {
                    Class> transformerClass =
                        (Class>)transformerDeclaration.loadClass();
                    try {
                        Constructor> constructor = transformerClass.getConstructor();
                        transformer = constructor.newInstance();
                    } catch (NoSuchMethodException e) {
                        Constructor> constructor =
                            transformerClass.getConstructor(ExtensionPointRegistry.class);
                        transformer = constructor.newInstance(registry);
                    }
                } catch (Exception e) {
                    throw new IllegalStateException(e);
                }
            }
            return transformer;
        }

        public String getSourceDataBinding() {
            return source;
        }

        public String getTargetDataBinding() {
            return target;
        }

        public int getWeight() {
            return weight;
        }

        public void transform(Object source, Object sink, TransformationContext context) {
            getTransformer().transform(source, sink, context);
        }

        @Override
        public String toString() {
            StringBuffer sb = new StringBuffer(super.toString());
            sb.append(";className=").append(transformerDeclaration.getClassName());
            return sb.toString();
        }
    }

    //FIXME The following methods should be on a different class from
    // extension point

    public List getTransformerChain(String sourceType, String resultType) {
        loadTransformers();

        String source = sourceType;
        String result = resultType;
        List transformers = new ArrayList();
        // First check if there is a direct path, if yes, use it regardless of the weight
        DirectedGraph.Edge link = graph.getEdge(sourceType, resultType);
        if (link != null) {
            transformers.add(link.getValue());
        } else {
            DirectedGraph.Path path = graph.getShortestPath(source, result);
            if (path == null) {
                return null;
            }
            for (DirectedGraph.Edge edge : path.getEdges()) {
                transformers.add(edge.getValue());
            }
        }
        return transformers;
    }

    @Override
    public String toString() {
        loadTransformers();

        return graph.toString();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy