All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.snapscript.core.link.ImportProcessor Maven / Gradle / Ivy

package org.snapscript.core.link;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;

import org.snapscript.common.Cache;
import org.snapscript.common.LazyBuilder;
import org.snapscript.common.LazyCache;
import org.snapscript.core.Context;
import org.snapscript.core.Entity;
import org.snapscript.core.NameChecker;
import org.snapscript.core.NameFormatter;
import org.snapscript.core.error.InternalStateException;
import org.snapscript.core.module.FilePathConverter;
import org.snapscript.core.module.Module;
import org.snapscript.core.module.Path;
import org.snapscript.core.module.PathConverter;
import org.snapscript.core.type.Type;
import org.snapscript.core.type.TypeLoader;

public class ImportProcessor implements ImportManager {

   private final Map generics;
   private final Map aliases;
   private final Set imports;
   private final ImportMatcher matcher;
   private final EntityFinder finder;
   private final Module parent;
   private final String from;
   private final String local;
   
   public ImportProcessor(Module parent, Executor executor, Path path, String from, String local) {
      this.generics = new ConcurrentHashMap();
      this.aliases = new ConcurrentHashMap();
      this.imports = new CopyOnWriteArraySet();
      this.matcher = new ImportMatcher(parent, executor, path, from);
      this.finder = new EntityFinder(parent);
      this.parent = parent;
      this.local = local;
      this.from = from;
   }
   
   @Override
   public void addImport(String prefix) {
      imports.add(prefix);
   }
   
   @Override
   public void addImport(String type, String alias) {
      aliases.put(alias, type);
   }
   
   @Override
   public void addImport(Type type, String alias) {
      generics.put(alias, type);
   }
   
   @Override
   public void addImports(Module module) {
      ImportManager manager = module.getManager();

      if(manager != null) {
         Set types = aliases.keySet();
         
         for(String type : types) {
            String alias = aliases.get(type);
            
            if(alias != null) {
               manager.addImport(type, alias);
            }
         }
         for(String value : imports) {
            manager.addImport(value);
         }
      }
   }
   
   public Type getType(String name) throws Exception {
      Future future = getImport(name); // import tetris.game.*
      
      if(future != null) {
         Entity entity = future.get();
         
         if(Type.class.isInstance(entity)) {
            return (Type)entity;
         }         
      }
      return null;
   }
   
   public Module getModule(String name) throws Exception {
      Future future = getImport(name); // import tetris.game.*
      
      if(future != null) {
         Entity entity = future.get();
         
         if(Module.class.isInstance(entity)) {
            return (Module)entity;
         }         
      }
      return null;
   }
   
   @Override
   public Future getImport(String name) {
      return finder.find(name);
   }   
   
   private class EntityFinder implements LazyBuilder> {
   
      private final Cache> cache;
      private final EntityResolver resolver;
      private final NameFormatter formatter;
      private final NameChecker filter;
      
      public EntityFinder(Module parent) {
         this.cache = new LazyCache>(this);
         this.resolver = new EntityResolver(parent);
         this.formatter = new NameFormatter();
         this.filter = new NameChecker(true);
      }
      
      public Future find(String name) {
         return cache.fetch(name);
      }
            
      @Override
      public Future create(String name) {
         try {                 
            String inner = formatter.formatInnerName(name);
            String origin = formatter.formatLocalName(name);

            if(!filter.isEntity(inner)) {
               return null;
            }
            if(!filter.isEntity(origin)) {
               return null;
            }
            if(origin.equals(local)) {
               return new ImportFuture(parent);
            }
            return resolver.resolve(name);
         } catch(Exception e){
            throw new InternalStateException("Could not find '" + name + "' in '" + from + "'", e);
         }
      }
   }
   
   private class EntityResolver {
      
      private final ImportEntityResolver resolver;
      private final PathConverter converter;
      private final NameFormatter formatter;
      
      public EntityResolver(Module parent) {
         this.resolver = new ImportEntityResolver(parent);
         this.converter = new FilePathConverter();
         this.formatter = new NameFormatter();
      }
      
      public Future resolve(String name) throws Exception {
         String origin = formatter.formatLocalName(name);
         Future entity = resolveGeneric(name);
         
         if(entity == null) {
            entity = resolveImport(name);
         }
         if(entity == null) {
            entity = resolveImport(origin);
         }
         if(entity == null) {
            entity = resolveDefault(name);
         }
         if(entity == null) {
            entity = resolveLocal(name);
         }
         return entity;
      }
      
      private Future resolveGeneric(String name) throws Exception{
         Entity entity = generics.get(name);
         
         if(entity != null) {                  
            return new ImportFuture(entity);
         } 
         return null;
      }
      
      private Future resolveImport(String name) throws Exception{         
         String alias = aliases.get(name);
         int index = name.indexOf("."); 
         
         if(alias != null) {
            String suffix = formatter.formatShortName(name);
            String prefix = converter.createModule(alias);         
            Entity entity = resolver.resolveEntity(alias);
            
            if(entity == null) {
               entity = resolver.resolveEntity(prefix, suffix);
            }           
            if(entity != null) {            
               return new ImportFuture(entity);
            }
         }  
         if(index == -1) {
            for(String module : imports) {
               Entity entity = resolver.resolveEntity(module, name); // this is "tetris.game.*"
               
               if(entity != null) {
                  return new ImportFuture(entity);
               }
            }
         }
         return null;
      }
      
      private Future resolveLocal(String name) throws Exception{
         Context context = parent.getContext();
         TypeLoader loader = context.getLoader();
         String origin = formatter.formatLocalName(name);
         int index = name.indexOf(".");     
         
         if(index == -1) {          
            Entity entity = loader.loadType(from, name);
               
            if(entity == null) {                      
               Future future = matcher.matchImport(imports, origin);
            
               if(name.endsWith(origin)) {
                  return (Future)future;
               }
               entity = loader.loadType(from, name);
            }               
            if(entity != null) {                  
               return new ImportFuture(entity);
            }            
         }  
         return null;
      }
      
      private Future resolveDefault(String name) throws Exception{ 
         Context context = parent.getContext();
         TypeLoader loader = context.getLoader();       
         Entity entity = loader.loadType(null, name); // null is "java.*"
            
         if(entity != null) {                  
            return new ImportFuture(entity);
         }            
         return null;
      }
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy