package org.jetbrains.plugins.ruby.motion.bridgesupport; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.plugins.ruby.motion.RubyMotionUtil; import org.jetbrains.plugins.ruby.ruby.RubyUtil; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.*; /** * @author Dennis.Ushakov */ public class FrameworkDependencyResolver { private static final Logger LOG = Logger.getInstance(InheritanceInfoHolder.class); private Map<String, Map<String, List<String>>> myDependencyInfo = new HashMap<>(); private final BridgeSupportLoader myLoader; public static FrameworkDependencyResolver getInstance() { return ServiceManager.getService(FrameworkDependencyResolver.class); } public FrameworkDependencyResolver(final BridgeSupportLoader loader) { myLoader = loader; final String path = RubyUtil.getScriptFullPath("rb/motion"); final File file = new File(path); if (file.exists() && file.isDirectory()) { for (File child : file.listFiles()) { final String name = child.getName(); if (name.endsWith(".yaml") && name.startsWith("dependencies.")) { try { final FileInputStream is = new FileInputStream(child); try { final Map map = RubyUtil.loadYaml(is); final Map<String, List<String>> result = new HashMap<>(); for (Object key : map.keySet()) { final ArrayList list = (ArrayList)map.get(key); final List<String> stringList = new ArrayList<>(list.size()); for (Object o : list) { stringList.add(o.toString()); } result.put(key.toString(), stringList); } myDependencyInfo.put(name.replaceAll("dependencies.", "").replaceAll(".yaml", ""), result); } finally { is.close(); } } catch (IOException e) { LOG.error(e); } } } } } public Collection<Framework> getFrameworks(final Module module) { final String sdkVersion = RubyMotionUtil.getInstance().getSdkVersion(module); final String[] frameworks = RubyMotionUtil.getInstance().getRequiredFrameworks(module); Map<String, List<String>> dependencyInfo = myDependencyInfo.get(sdkVersion); if (dependencyInfo == null) { LOG.warn("Could not find dependency info for version: '" + sdkVersion + "'"); if (RubyMotionUtil.getInstance().isOSX(module)) { dependencyInfo = myDependencyInfo.get("10.10"); } else if (!RubyMotionUtil.getInstance().isAndroid(module)) { dependencyInfo = myDependencyInfo.get("9.3"); } } final Set<Framework> result = new HashSet<>(); final Queue<String> unsatisfied = new LinkedList<>(); final Set<String> processed = new HashSet<>(); Collections.addAll(unsatisfied, frameworks); while (!unsatisfied.isEmpty()) { final String name = unsatisfied.poll(); if (processed.contains(name)) continue; ContainerUtil.addIfNotNull(result, myLoader.getFramework(sdkVersion, name)); final List<String> deps = dependencyInfo != null ? dependencyInfo.get(name) : null; if (deps != null) { unsatisfied.addAll(deps); } processed.add(name); } return result; } }