/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.eas.client; import com.eas.client.cache.ActualCache; import com.eas.client.cache.ModelsDocuments; import com.eas.client.cache.ApplicationSourceIndexer; import com.eas.client.cache.PlatypusFiles; import com.eas.client.model.store.Model2XmlDom; import com.eas.client.scripts.DependenciesWalker; import com.eas.client.settings.SettingsConstants; import com.eas.script.Scripts; import com.eas.util.FileUtils; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Callable; import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * * @author mg */ public class LocalModulesProxy implements ModulesProxy { public static Set<String> extractQueriesRefs(Element aNode, String aEntityTagsName, String aQueryRefAttrName) throws DOMException { Set<String> refs = new HashSet<>(); NodeList entitiesNodes = aNode.getElementsByTagName(aEntityTagsName); for (int i = entitiesNodes.getLength() - 1; i >= 0; i--) { Node entityNode = entitiesNodes.item(i); Node queryIdAttribute = entityNode.getAttributes().getNamedItem(aQueryRefAttrName); if (queryIdAttribute != null) { String sQueryName = queryIdAttribute.getNodeValue(); refs.add(sQueryName); } } return refs; } protected final ApplicationSourceIndexer indexer; protected final ModelsDocuments modelsDocs; protected final ActualCache<ModuleStructure> structures = new ActualCache<ModuleStructure>() { @Override protected ModuleStructure parse(String name, File file) throws Exception { ModuleStructure structure = new ModuleStructure(); structure.getParts().addFile(file); String jsSource = FileUtils.readString(file, SettingsConstants.COMMON_ENCODING); DependenciesWalker walker = new DependenciesWalker(jsSource, (String aModuleCandidate) -> { File depFile = indexer.nameToFile(aModuleCandidate); if (depFile != null && depFile.exists()) { if (depFile.getName().endsWith(PlatypusFiles.JAVASCRIPT_FILE_END)) { return true; } else { Logger.getLogger(LocalModulesProxy.class.getName()).log(Level.WARNING, "JavaScript identifier: {0} found that is the same with non-module application element.", aModuleCandidate); } }// ordinary script class return false; }); walker.walk(); structure.getClientDependencies().addAll(walker.getDependencies()); structure.getServerDependencies().addAll(walker.getServerDependencies()); //Query dependencies from loadEntity() calls structure.getQueryDependencies().addAll(walker.getQueryDependencies()); Path jsPath = Paths.get(file.toURI()); String jsedName = jsPath.getFileName().toString(); String woExtension = jsedName.substring(0, jsedName.length() - PlatypusFiles.JAVASCRIPT_EXTENSION.length()); File modelFile = jsPath.resolveSibling(woExtension + PlatypusFiles.MODEL_EXTENSION).toFile(); if (modelFile.exists()) { structure.getParts().addFile(modelFile); //Query dependencies from model's xml Document modelDoc = modelsDocs.get(jsPath.toString(), modelFile);// cache documents by file of bundle (not by module name) if (modelDoc != null) { Element rootNode = modelDoc.getDocumentElement(); structure.getQueryDependencies().addAll(extractQueriesRefs(rootNode, Model2XmlDom.ENTITY_TAG_NAME, Model2XmlDom.QUERY_ID_ATTR_NAME)); structure.getQueryDependencies().addAll(extractQueriesRefs(rootNode, "e", "qi")); } } File layoutFile = jsPath.resolveSibling(woExtension + PlatypusFiles.FORM_EXTENSION).toFile(); if (layoutFile.exists()) { structure.getParts().addFile(layoutFile); } return structure; } }; protected final String startModuleName; public LocalModulesProxy(ApplicationSourceIndexer aIndexer, ModelsDocuments aModelsDocs, String aStartModuleName) throws Exception { super(); indexer = aIndexer; modelsDocs = aModelsDocs; if (aStartModuleName != null && aStartModuleName.toLowerCase().endsWith(PlatypusFiles.JAVASCRIPT_FILE_END)) { startModuleName = aStartModuleName.substring(0, aStartModuleName.length() - PlatypusFiles.JAVASCRIPT_FILE_END.length()); } else { startModuleName = aStartModuleName; } } @Override public Path getLocalPath() { return indexer.getAppPath(); } @Override public ModuleStructure getModule(String aName, Scripts.Space aSpace, Consumer<ModuleStructure> onSuccess, Consumer<Exception> onFailure) throws Exception { Callable<ModuleStructure> doWork = () -> { String name = aName; if (name == null || name.isEmpty()) { if (startModuleName == null || startModuleName.isEmpty()) { throw new IllegalStateException("Default application element must present if you whant to resolve empty string names."); } name = startModuleName; } if (name != null) { File file = indexer.nameToFile(name); if (file != null && file.getName().endsWith(PlatypusFiles.JAVASCRIPT_FILE_END)) { return structures.get(file.getAbsolutePath(), file); } else { return null; } } else { return null; } }; if (onSuccess != null) { try { ModuleStructure structure = doWork.call(); aSpace.process(() -> { onSuccess.accept(structure); }); } catch (Exception ex) { if (onFailure != null) { aSpace.process(() -> { onFailure.accept(ex); }); } } return null; } else { return doWork.call(); } } @Override public File getResource(String aResourceName, Scripts.Space aSpace, Consumer<File> onSuccess, Consumer<Exception> onFailure) throws Exception { Callable<File> doWork = () -> { String relativePath = aResourceName.replace("/", File.separator); Path resolved = indexer.getAppPath().resolve(relativePath); return resolved.toFile(); }; if (onSuccess != null) { try { File structure = doWork.call(); aSpace.process(() -> { onSuccess.accept(structure); }); } catch (Exception ex) { if (onFailure != null) { aSpace.process(() -> { onFailure.accept(ex); }); } } return null; } else { return doWork.call(); } } @Override public File nameToFile(String aName) throws Exception { return indexer.nameToFile(aName); } @Override public String getDefaultModuleName(File aFile) { return indexer.getDefaultModuleName(aFile); } }