/** * Copyright (c) 2013-2016 Angelo ZERR. * 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: * Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation */ package tern.utils; import static tern.utils.ExtensionUtils.JSON_EXTENSION; import static tern.utils.ExtensionUtils.JS_EXTENSION; import static tern.utils.ExtensionUtils.TERN_SUFFIX; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.eclipsesource.json.JsonObject; import com.eclipsesource.json.JsonValue; import tern.ITernProject; import tern.TernException; import tern.metadata.ModuleDependenciesComparator; import tern.metadata.TernModuleMetadata; import tern.metadata.TernModuleMetadataManager; import tern.repository.ITernRepository; import tern.server.BasicTernDef; import tern.server.BasicTernPlugin; import tern.server.ITernDef; import tern.server.ITernModule; import tern.server.ITernModuleConfigurable; import tern.server.ITernPlugin; import tern.server.ModuleType; import tern.server.TernModuleConfigurable; import tern.server.TernModuleInfo; /** * Helper for {@link ITernModule}. * */ public class TernModuleHelper { private TernModuleHelper() { } /** * Group the given list tern modules by {@link ITernModule#getType()}. * * @param modules * @param groupedModules */ public static List<ITernModule> groupByType(List<ITernModule> modules) { List<ITernModule> groupedModules = new ArrayList<ITernModule>(); Map<String, TernModuleConfigurable> wrappers = null; for (ITernModule module : modules) { if (!isConfigurableModule(module)) { // module is not configurable, add it groupedModules.add(module); } else { // module is configurable (version can be customized, or // options), wrap it with TernModuleConfigurable if (wrappers == null) { wrappers = new HashMap<String, TernModuleConfigurable>(); } TernModuleConfigurable wrapper = wrappers.get(module.getType()); if (wrapper == null) { wrapper = new TernModuleConfigurable(module); wrappers.put(module.getType(), wrapper); groupedModules.add(wrapper); } else { wrapper.addModule(module); } } } return groupedModules; } /** * Returns true if the given module can be configured and false otherwise. * * @param module * @return true if the given module can be configured and false otherwise. */ public static boolean isConfigurableModule(ITernModule module) { TernModuleMetadata metadata = module.getMetadata(); return !StringUtils.isEmpty(module.getVersion()) || (metadata != null && (metadata.hasOptions() || metadata.isLinter())); } /** * Update the given list of {@link ITernDef} or {@link ITernPlugin} by using * the given module. * * @param module * @param defs * to update. * @param plugins * to update. */ public static void update(List<ITernDef> defs, List<ITernPlugin> plugins, ITernModule module) { update(defs, plugins, null, module); } /** * Update the given list of {@link ITernDef} or {@link ITernPlugin} by using * the given module. * * @param module * @param defs * to update. * @param plugins * to update. */ private static void update(List<ITernDef> defs, List<ITernPlugin> plugins, JsonValue options, ITernModule module) { switch (module.getModuleType()) { case Def: defs.add((ITernDef) module); break; case Plugin: plugins.add((ITernPlugin) module); break; case Configurable: ITernModule wrappedModule = ((ITernModuleConfigurable) module).getWrappedModule(); JsonValue wrappedOptions = ((ITernModuleConfigurable) module).getOptions(); update(defs, plugins, wrappedOptions, wrappedModule); break; } } /** * Update the given tern project by using the given module. * * @param module * @param ternProject */ public static void update(ITernModule module, ITernProject ternProject) { update(module, null, ternProject); } /** * Update the given tern project by using the given module. * * @param module * @param ternProject */ public static void update(ITernModule module, JsonValue options, ITernProject ternProject) { switch (module.getModuleType()) { case Def: ternProject.addLib((ITernDef) module); break; case Plugin: ternProject.addPlugin((ITernPlugin) module, options); break; case Configurable: ITernModule wrappedModule = ((ITernModuleConfigurable) module).getWrappedModule(); JsonValue wrappedOptions = ((ITernModuleConfigurable) module).getOptions(); update(wrappedModule, wrappedOptions, ternProject); break; } } /** * Retrieve {@link ITernModuleConfigurable} for the given module inside the * list of modules. * * @param module * @param options * @param allModules * @return * @throws TernException */ public static ITernModuleConfigurable findConfigurable(ITernModule module, JsonValue options, List<ITernModule> allModules) throws TernException { String version = module.getVersion(); ITernModuleConfigurable c; for (ITernModule f : allModules) { if (f.getModuleType() == ModuleType.Configurable && f.getType().equals(module.getType())) { c = ((ITernModuleConfigurable) f); if (!StringUtils.isEmpty(version)) { c.setVersion(version); } if (options != null) { if (options.isObject()) { // set a copy of the options. c.setOptions(new JsonObject((JsonObject) options)); } else if (options.isNull()) { c.setOptions(options); } } return (ITernModuleConfigurable) f; } } return null; } /** * Returns true if the given module has options and false otherwise. * * @param module * @return true if the given module has options and false otherwise. */ public static boolean hasOptions(ITernModule module) { if (module == null || module.getMetadata() == null) { return false; } return module.getMetadata().hasOptions(); } public static ITernModule createModule(File file, ITernRepository repository, ITernRepository defaultRepository) { String filename = file.getName(); if (file.isDirectory()) { if (filename.startsWith(TERN_SUFFIX)) { // the folder follows the syntax tern-{name} where name is the // tern plugin name. TernModuleInfo info = new TernModuleInfo(filename.substring(TERN_SUFFIX.length(), filename.length())); // try to get local or repository metadata. TernModuleMetadata metadata = getMetadata(info.getType(), file, repository, defaultRepository); if (metadata != null && metadata.isDef()) { return new BasicTernDef(info, metadata); } return new BasicTernPlugin(info, metadata); } } else if (file.isFile()) { // the module is (local file), try and guess the module type (*.json // or *.js) return createModule(filename, repository, defaultRepository); } return null; } /** * Create tern module from the given file name and null if it's not a tern * module. * * @param filename * @return tern module from the given file name and null if it's not a tern * module. */ public static ITernModule createModule(String filename, ITernRepository repository, ITernRepository defaultRepository) { int index = filename.lastIndexOf('.'); if (index == -1) { // the file has none file extension, it's not a tern plugin. return null; } String fileExtension = filename.substring(index + 1, filename.length()); filename = filename.substring(0, index); if (fileExtension.equals(JSON_EXTENSION)) { // the file is JSON file, it's a tern JSON Type Definition TernModuleInfo info = new TernModuleInfo(filename); TernModuleMetadata metadata = getMetadata(info.getType(), null, repository, defaultRepository); return new BasicTernDef(info, metadata); } else if (fileExtension.equals(JS_EXTENSION)) { // the file is JavaScript file, it's a tern plugin TernModuleInfo info = new TernModuleInfo(filename); TernModuleMetadata metadata = getMetadata(info.getType(), null, repository, defaultRepository); return new BasicTernPlugin(info, metadata); } // it's not a tern module return null; } /** * Retrieve module metadata from the given module type and null otherwise. * * @param moduleName * @param moduleDir * search file metadata/${moduleName}.metadata.json * @param repository * otherwise search in the repository of the module * @param defaultRepository * otherwise search in the default repository. * @return module metadata from the given module type and null otherwise. */ private static TernModuleMetadata getMetadata(String moduleName, File moduleDir, ITernRepository repository, ITernRepository defaultRepository) { TernModuleMetadata metadata = null; if (moduleDir != null && moduleDir.isDirectory()) { try { metadata = TernModuleMetadataManager.loadMetadata(moduleDir, moduleName); } catch (IOException e) { e.printStackTrace(); } } if (metadata == null && repository != null) { metadata = repository.getDefaultMetadata(moduleName); } if (metadata == null && defaultRepository != null) { metadata = defaultRepository.getDefaultMetadata(moduleName); } return metadata; } /** * Returns the file path as string. * * @param file * @return the file path as string. */ public static String getPath(File file) { try { return file.getCanonicalPath(); } catch (IOException e) { return file.getPath(); } } /** * Returns the file name of the given tern module. * * @param module * @return the file name of the given tern module. */ public static String getFileName(ITernModule module) { switch (module.getModuleType()) { case Def: return new StringBuilder(module.getName()).append('.').append(JSON_EXTENSION).toString(); default: return new StringBuilder(module.getName()).append('.').append(JS_EXTENSION).toString(); } } /** * Sort the given list of modules by dependencies. * * @param modules */ public static void sort(List<ITernModule> modules) { sort(modules, null); } public static void sort(List<ITernModule> modules, TernModuleMetadataManager manager) { new ModuleDependenciesComparator(modules, manager); } /** * Format list modules as string. * * @return format list modules as string. */ public static String getModulesAsString(ITernModule... modules) { StringBuilder s = new StringBuilder(); for (int i = 0; i < modules.length; i++) { if (i > 0) { s.append(","); } s.append(modules[i].getName()); } return s.toString(); } /** * Returns the label of the given module. * * @param module * @return the label of the given module. */ public static String getLabel(ITernModule module) { try { TernModuleMetadata metadata = module.getMetadata(); if (metadata != null && !StringUtils.isEmpty(metadata.getLabel())) { return metadata.getLabel(); } } catch (Exception e) { // Exception can be thrown if TernPlugin enum is used. } return module.getName(); } }