org.sourcepit.b2.internal.maven.ModelContextAdapterFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.sourcepit.b2.internal.maven.ModelContextAdapterFactory.java

Source

/*
 * Copyright 2014 Bernd Vogt and others.
 * 
 * Licensed 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.sourcepit.b2.internal.maven;

import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.sourcepit.b2.maven.core.B2MavenBridge;
import org.sourcepit.b2.model.interpolation.internal.module.B2MetadataUtils;
import org.sourcepit.b2.model.module.AbstractModule;
import org.sourcepit.b2.model.module.FeatureProject;
import org.sourcepit.b2.model.module.FeaturesFacet;
import org.sourcepit.common.maven.model.MavenArtifact;

import com.google.common.base.Optional;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.SetMultimap;

@Named
public class ModelContextAdapterFactory {
    private final ModuleArtifactResolver artifactResolver;

    @Inject
    public ModelContextAdapterFactory(ModuleArtifactResolver artifactResolver) {
        this.artifactResolver = artifactResolver;
    }

    public ModelContext adapt(MavenSession session, MavenProject project) {
        synchronized (project) {
            ModelContext context = (ModelContext) project.getContextValue(ModelContext.class.getName());
            if (context == null) {
                context = createModuleModelContext(session, project);
                project.setContextValue(ModelContext.class.getName(), context);
            }
            return context;
        }
    }

    public static ModelContext get(MavenProject project) {
        synchronized (project) {
            return (ModelContext) project.getContextValue(ModelContext.class.getName());
        }
    }

    private ModelContext createModuleModelContext(MavenSession session, MavenProject project) {
        final ResourceSet resourceSet = createResourceSet();

        final SetMultimap<URI, String> scopeTest = LinkedHashMultimap.create();
        initURIMapping(resourceSet, scopeTest, session, project, "test");

        final SetMultimap<URI, String> scopeCompile = LinkedHashMultimap.create();
        initURIMapping(resourceSet, scopeCompile, session, project, "compile");

        initURIMapping(resourceSet, session, project);

        final URI artifactURI = B2MavenBridge.toArtifactURI(project, "module", null);
        final URI fileURI = URI.createFileURI(pathOfMetaDataFile(project.getBasedir(), "b2.module"));
        resourceSet.getURIConverter().getURIMap().put(artifactURI, fileURI);

        return new ModelContext(resourceSet, artifactURI.appendFragment("/"), resolve(resourceSet, scopeCompile),
                resolve(resourceSet, scopeTest));
    }

    private void initURIMapping(ResourceSet resourceSet, MavenSession session, MavenProject currentProject) {
        final Map<URI, URI> uriMap = resourceSet.getURIConverter().getURIMap();

        final List<MavenProject> projects = session.getProjects();
        for (int i = 0; i < projects.indexOf(currentProject); i++) {
            final ModelContext foreignModelContext = ModelContextAdapterFactory.get(projects.get(i));
            if (foreignModelContext != null) {
                final Map<URI, URI> foreignUriMap = foreignModelContext.getResourceSet().getURIConverter()
                        .getURIMap();
                for (URI uri : foreignUriMap.keySet()) {
                    if (!uriMap.containsKey(uri)) {
                        uriMap.put(uri, foreignUriMap.get(uri));
                    }
                }
            }
        }
    }

    private static SetMultimap<AbstractModule, FeatureProject> resolve(ResourceSet resourceSet,
            SetMultimap<URI, String> unresolved) {
        final SetMultimap<AbstractModule, FeatureProject> resolved = LinkedHashMultimap.create(unresolved.size(),
                4);
        for (Entry<URI, Collection<String>> entry : unresolved.asMap().entrySet()) {
            final URI uri = entry.getKey();
            final AbstractModule module = (AbstractModule) resourceSet.getResource(uri, true).getContents().get(0);

            for (String classifier : entry.getValue()) {
                final Optional<FeatureProject> result = findAssemblyFeatureForClassifier(module, classifier);
                if (!result.isPresent()) {
                    throw new IllegalStateException(
                            "Cannot determine assembly feature for classifier '" + classifier + "'");
                }
                resolved.get(module).add(result.get());
            }
        }
        return resolved;
    }

    private static Optional<FeatureProject> findAssemblyFeatureForClassifier(final AbstractModule module,
            String classifier) {
        for (FeaturesFacet featuresFacet : module.getFacets(FeaturesFacet.class)) {
            for (FeatureProject featureProject : featuresFacet.getProjects()) {
                final int idx = B2MetadataUtils.getAssemblyClassifiers(featureProject).indexOf(classifier);
                if (idx > -1) {
                    return Optional.of(featureProject);
                }
            }
        }
        return Optional.absent();
    }

    // TODO use interpolation layout
    private static String pathOfMetaDataFile(File directory, String name) {
        final StringBuilder sb = new StringBuilder();
        final String modulePath = directory.getAbsolutePath();
        if (modulePath.length() != 0) {
            sb.append(modulePath);
            sb.append(File.separatorChar);
        }
        sb.append(".b2");
        sb.append(File.separatorChar);
        sb.append(name);
        return sb.toString();
    }

    private static ResourceSet createResourceSet() {
        final ResourceSet resourceSet = new ResourceSetImpl();
        resourceSet.getResourceFactoryRegistry().getProtocolToFactoryMap().put("gav", new XMIResourceFactoryImpl());
        resourceSet.getResourceFactoryRegistry().getProtocolToFactoryMap().put("file",
                new XMIResourceFactoryImpl());
        return resourceSet;
    }

    private void initURIMapping(ResourceSet resourceSet, SetMultimap<URI, String> artifactURIs,
            MavenSession session, MavenProject project, String scope) {
        // resolve module artifacts
        final SetMultimap<MavenArtifact, String> moduleArtifactToClassifiers = artifactResolver.resolve(session,
                project, scope);

        // create artifact to file uri mapping
        for (Entry<MavenArtifact, Collection<String>> entry : moduleArtifactToClassifiers.asMap().entrySet()) {
            final MavenArtifact artifact = entry.getKey();
            final URI artifactURI = toArtifactURI(artifact, null);
            final URI fileURI = URI.createFileURI(artifact.getFile().getAbsolutePath());
            artifactURIs.get(artifactURI).addAll(entry.getValue());
            resourceSet.getURIConverter().getURIMap().put(artifactURI, fileURI);
        }
    }

    private static URI toArtifactURI(MavenArtifact artifact, String classifier) {
        final StringBuilder sb = new StringBuilder();
        sb.append(artifact.getGroupId());
        sb.append("/");
        sb.append(artifact.getArtifactId());
        sb.append("/");
        sb.append(artifact.getType());
        if (classifier != null && classifier.length() > 0) {
            sb.append("/");
            sb.append(classifier);
        }
        sb.append("/");
        sb.append(artifact.getVersion());
        return URI.createURI("gav:/" + sb.toString());
    }

}