/** * Copyright (c) 2011 Cloudsmith Inc. and other contributors, as listed below. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cloudsmith * */ package org.cloudsmith.geppetto.pp.dsl.ui.container; import java.io.File; import java.util.Collections; import java.util.List; import org.apache.log4j.Logger; import org.cloudsmith.geppetto.diagnostic.Diagnostic; import org.cloudsmith.geppetto.forge.Forge; import org.cloudsmith.geppetto.forge.v2.model.Dependency; import org.cloudsmith.geppetto.forge.v2.model.Metadata; import org.cloudsmith.geppetto.forge.v2.model.ModuleName; import org.cloudsmith.geppetto.semver.Version; import org.cloudsmith.geppetto.semver.VersionRange; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.xtext.ui.XtextProjectHelper; import org.eclipse.xtext.ui.containers.AbstractStorage2UriMapperClient; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.google.common.collect.Lists; import com.google.inject.Inject; /** * Helper for Puppet Projects. * */ public class PPWorkspaceProjectsStateHelper extends AbstractStorage2UriMapperClient { private final static Logger log = Logger.getLogger(PPWorkspaceProjectsStateHelper.class); @Inject private IWorkspace workspace; @Inject private Forge forge; /** * Returns the best matching project (or null if there is no match) among the projects in the * workspace. * A translation is made from "/" to "-" in the separators in dependencies. (Should be checked elsewhere). * * @param d * @return */ protected IProject getBestMatchingProject(Dependency d) { ModuleName name = d.getName(); if(name == null) return null; // Names with "/" are not allowed name = name.withSeparator('-'); String namepart = name + "-"; BiMap<IProject, Version> candidates = HashBiMap.create(); int len = namepart.length(); for(IProject p : getWorkspaceRoot().getProjects()) { String n = p.getName(); if(n.startsWith(namepart) && n.length() > len && isAccessibleXtextProject(p)) { try { candidates.put(p, Version.create(p.getName().substring(len))); } catch(IllegalArgumentException e) { // Project name does not end with a valid version. Just skip it } } } if(candidates.isEmpty()) return null; VersionRange vr = d.getVersionRequirement(); if(vr == null) vr = VersionRange.ALL_INCLUSIVE; Version best = vr.findBestMatch(candidates.values()); return candidates.inverse().get(best); } public List<String> getVisibleProjectNames(IProject project) { if(isAccessibleXtextProject(project)) { File moduleDir = project.getLocation().toFile(); List<String> result = Lists.newArrayList(); // parse the "Modulefile/metadata.json" and get full name and version, use this as name of target entry // TODO: Improve this to report diagnostics try { Diagnostic diag = new Diagnostic(); Metadata metadata = forge.createFromModuleDirectory(moduleDir, false, null, null, diag); if(metadata != null) { for(Dependency d : metadata.getDependencies()) { IProject best = getBestMatchingProject(d); if(best != null) result.add(best.getName()); else { // TODO: need to inform the user about this somehow, but can't create markers here } } } } catch(Exception e) { if(log.isDebugEnabled()) log.debug("Could not parse any metadata from project: '" + project.getName() + "'", e); } return result; } return Collections.emptyList(); } protected IWorkspaceRoot getWorkspaceRoot() { return workspace.getRoot(); } /** * Initializes visible handles from PP 'Modulefile/metadata.json' manifests. In case of errors, a partially * parsed result is returned and error is logged. * * @param handle * @return */ public List<String> initVisibleHandles(String handle) { IProject project = getWorkspaceRoot().getProject(handle); return getVisibleProjectNames(project); } protected boolean isAccessibleXtextProject(IProject p) { return p != null && XtextProjectHelper.hasNature(p); } public void setWorkspace(IWorkspace workspace) { this.workspace = workspace; } }