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

gw.lang.gosuc.Gosuc Maven / Gradle / Ivy

There is a newer version: 1.18.2
Show newest version
/*
 * Copyright 2014 Guidewire Software, Inc.
 */

package gw.lang.gosuc;

import gw.config.CommonServices;
import gw.config.IGlobalLoaderProvider;
import gw.config.IMemoryMonitor;
import gw.fs.IDirectory;
import gw.lang.GosuShop;
import gw.lang.init.GosuInitialization;
import gw.lang.parser.IGosuParser;
import gw.lang.reflect.IType;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.java.JavaTypes;
import gw.lang.reflect.module.Dependency;
import gw.lang.reflect.module.IExecutionEnvironment;
import gw.lang.reflect.module.IJreModule;
import gw.lang.reflect.module.IModule;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 */
public class Gosuc implements IGosuc {

  private GosucProject _project;
  private IModule _globalModule;
  private List _allGosucModules;

  public Gosuc( String projectFile, ICustomParser custParser ) throws FileNotFoundException {
    File file = new File( projectFile );
    if( !file.isFile() ) {
      System.err.println( "The project file does not exist: " + file );
    }
    FileInputStream is = new FileInputStream( file );
    _project = GosucProjectParser.parse( new BufferedInputStream( is ), custParser );
    _allGosucModules = _project.getModules();
  }

  public Gosuc( ICustomParser custParser, String projectFileContent ) throws FileNotFoundException {
    _project = GosucProjectParser.parse( projectFileContent, custParser );
    _allGosucModules = _project.getModules();
  }

  public void initializeGosu() {
    CommonServices.getKernel().redefineService_Privileged( IGlobalLoaderProvider.class,
            new GosucGlobalLoaderProvider( _project.getGlobalLoaders() ) );
    IMemoryMonitor memoryMonitor = _project.getMemoryMonitor();
    if (memoryMonitor != null) {
      CommonServices.getKernel().redefineService_Privileged(IMemoryMonitor.class, memoryMonitor);
    }
    IExecutionEnvironment execEnv = TypeSystem.getExecutionEnvironment( _project );
    List modules = defineModules( _project );
    modules.add( _globalModule );
    GosuInitialization.instance( execEnv ).initializeMultipleModules( modules );
    updateAllModuleClasspaths( _project );
    IModule module = execEnv.getModule( IExecutionEnvironment.GLOBAL_MODULE_NAME );
    TypeSystem.pushModule( module );
    try {
      Object o1 = IGosuParser.NaN;
      Object o2 = JavaTypes.DOUBLE();
    }
    finally {
      TypeSystem.popModule( module );
    }
    _project.startDependencies();
  }

  private List defineModules( GosucProject project ) {
    IExecutionEnvironment execEnv = TypeSystem.getExecutionEnvironment( project );
    execEnv.createJreModule( );
    _globalModule = GosuShop.createGlobalModule(execEnv);
    _globalModule.configurePaths( Collections.emptyList(), Collections.emptyList(), Collections.emptyList() );
    _globalModule.addDependency( new Dependency( execEnv.getJreModule(), true ) );

    List allSourcePaths = new ArrayList();
    Map modules = new HashMap();
    List allModules = new ArrayList();
    for( GosucModule gosucModule : _allGosucModules ) {
      IModule module = defineModule( project, gosucModule );
      if( module != null ) {
        allSourcePaths.addAll( module.getSourcePath() );
        modules.put( gosucModule.getName(), module );
        allModules.add( module );
      }
    }

    for( GosucModule gosucModule : _allGosucModules ) {
      IModule module = modules.get( gosucModule.getName() );
      for( GosucDependency dep : gosucModule.getDependencies() ) {
        IModule moduleDep = modules.get( dep.getModuleName() );
        if( moduleDep != null ) {
          module.addDependency( new Dependency( moduleDep, isExported( gosucModule, dep.getModuleName() ) ) );
        }
      }
    }

    addImplicitJreModuleDependency( project, allModules );
    allSourcePaths.addAll( execEnv.getJreModule().getSourcePath() );

    List rootModules = findRootModules(allModules);
    for (IModule rootModule : rootModules) {
      _globalModule.addDependency(new Dependency(rootModule, true));
    }
    _globalModule.setSourcePath( allSourcePaths );
    return allModules;
  }

  public List findRootModules(List modules) {
    List moduleRoots = new ArrayList(modules);
    for (IModule module : modules) {
      for (Dependency d : module.getDependencies()) {
        moduleRoots.remove(d.getModule());
      }
    }
    return moduleRoots;
  }

  public IModule defineModule( GosucProject project, GosucModule gosucModule ) {
    IModule gosuModule = GosuShop.createModule( TypeSystem.getExecutionEnvironment( project ),
                                                gosucModule.getName() );
    List sourceFolders = getSourceFolders( gosucModule );
    gosuModule.configurePaths( getClassPaths( gosucModule ), sourceFolders, getBackingSourcePaths( gosucModule ) );
    gosuModule.setNativeModule( gosucModule );
    gosuModule.setExcludedPaths(getExcludedFolders( gosucModule ));
    return gosuModule;
  }

  private List getSourceFolders( GosucModule gosucModule ) {
    List sourceFolders = new ArrayList();
    for( String path : gosucModule.getAllSourceRoots() ) {
      sourceFolders.add( GosucUtil.getDirectoryForPath( path ) );
    }
    return sourceFolders;
  }

  private List getExcludedFolders( GosucModule gosucModule ) {
    List excludedFolders = new ArrayList();
    for( String path : gosucModule.getExcludedRoots() ) {
      excludedFolders.add(GosucUtil.getDirectoryForPath(path));
    }
    return excludedFolders;
  }

  public boolean isExported( GosucModule gosucModule, String childModuleName ) {
    for( GosucDependency dep : gosucModule.getDependencies() ) {
      if( dep.getModuleName().equals( childModuleName ) ) {
        return dep.isExported();
      }
      if( isExported( findGosucModule( dep.getModuleName() ), childModuleName ) ) {
        return true;
      }
    }
    return false;
  }

  private GosucModule findGosucModule( String moduleName ) {
    for( GosucModule mod : _allGosucModules ) {
      if( mod.getName().equals( moduleName ) ) {
        return mod;
      }
    }
    return null;
  }

  private void addImplicitJreModuleDependency( GosucProject project, List modules ) {
    IJreModule jreModule = (IJreModule)TypeSystem.getExecutionEnvironment( project ).getJreModule();
    updateJreModuleWithProjectSdk( project, jreModule );
    for( IModule module : modules ) {
      module.addDependency( new Dependency( jreModule, true ) );
    }
    modules.add( jreModule );
  }

  protected void updateJreModuleWithProjectSdk( GosucProject project, IJreModule jreModule ) {
    GosucSdk projectSdk = project.getSdk();
    jreModule.configurePaths( GosucUtil.toDirectories( projectSdk.getPaths() ),
                              Collections.emptyList(),
                              GosucUtil.toDirectories( projectSdk.getBackingSourcePath() ) );
    jreModule.setNativeSDK( projectSdk );
  }

  void updateAllModuleClasspaths( GosucProject project ) {
    final List modules = TypeSystem.getExecutionEnvironment( project ).getModules();
    List gosucModules = new ArrayList();
    for( IModule module : modules ) {
      GosucModule gosucModule = (GosucModule)module.getNativeModule();
      if( gosucModule != null ) {
        gosucModules.add( gosucModule );
      }
    }

    // FIXME-isd: why do we need to update classpaths again?
    Map> classpathMap = createClassPathMap( gosucModules.toArray( new GosucModule[gosucModules.size()] ) );
    for( IModule module : modules ) {
      if( module.getNativeModule() != null ) {
        module.configurePaths( classpathMap.get( module.getName() ),
                               module.getSourcePath(),
                               module.getBackingSourcePath() );
      }
    }
  }

  private Map> createClassPathMap( GosucModule[] allGosucModules ) {
    Map> classpathMap = new HashMap>();

    for( GosucModule module : allGosucModules ) {
      String name = module.getName();
      List classPaths = getClassPaths( module );
      classpathMap.put( name, classPaths );
    }

    // simplify classpaths
    for( GosucModule module : allGosucModules ) {
      List referencedTotalClasspath = getReferencedTotalClasspath( module, classpathMap );
      if( referencedTotalClasspath != null ) {
        List claspath = classpathMap.get( module.getName() );
        for( Iterator i = claspath.iterator(); i.hasNext(); ) {
          IDirectory dir = i.next();
          if( referencedTotalClasspath.contains( dir ) ) {
            i.remove();
          }
        }
      }
    }

    return classpathMap;
  }


  private List getReferencedTotalClasspath( GosucModule gosucModule, Map> classpathMap ) {
    List totalClasspath = new ArrayList();
    List referencedModules = getAllRequiredModules( gosucModule );
    for( GosucModule m : referencedModules ) {
      totalClasspath.addAll( classpathMap.get( m.getName() ) );
    }
    return totalClasspath;
  }


  public List getAllRequiredModules( GosucModule gosucModule ) {
    Set visitedProjects = new HashSet();
    List modules = new ArrayList();
    getAllRequiredProjects( gosucModule, modules, visitedProjects );
    return modules;
  }

  private void getAllRequiredProjects( GosucModule gosucModule, List gosucModuleList, Set visitedModules ) {
    visitedModules.add( gosucModule );

    for( GosucDependency dep : gosucModule.getDependencies() ) {
      GosucModule depMod = findGosucModule( dep.getModuleName() );
      if( !visitedModules.contains( depMod ) ) {
        gosucModuleList.add( depMod );
        getAllRequiredProjects( depMod, gosucModuleList, visitedModules );
      }
    }
  }

  private static List getClassPaths(GosucModule gosucModule) {
    List paths = new ArrayList();
    for( String path : gosucModule.getClasspath() ) {
      paths.add( GosucUtil.getDirectoryForPath( path ) );
    }
    return paths;
  }

  private static List getBackingSourcePaths( GosucModule gosucModule ) {
    List paths = new ArrayList<>();
    for( String path : gosucModule.getBackingSourcePath() ) {
      paths.add( GosucUtil.getDirectoryForPath( path ) );
    }
    return paths;
  }

  public List compile( String moduleName, List types ) {
    IModule module = moduleName == null
                     ? TypeSystem.getGlobalModule()
                     : TypeSystem.getExecutionEnvironment().getModule( moduleName );
    return compile( module, types );
  }

  public List compile( IModule module, List types ) {
    TypeSystem.pushModule( module );
    try {
      return new GosucCompiler().compile( _project, types );
    }
    finally {
      TypeSystem.popModule( module );
    }
  }

  // You can use this for testing by:
  // - From an IJ project use the 'Write Gosuc Project' command to write out the project file
  // - Then run this from IJ using 'classpath of module' setting to match the proper module for pl/pc/cc etc. (this is so the global loaders will be in the classpath)
  public static void main( String[] args ) throws FileNotFoundException {
    String error = GosucArg.parseArgs( args );
    if( error != null ) {
      System.err.println( error );
      return;
    }
    String strFile = GosucArg.PROJECT.getValue();
    Gosuc gosuc = new Gosuc( strFile, maybeGetCustomParser() );
    gosuc.initializeGosu();
    gosuc.compile( (String)null, Collections.singletonList( "-all" ) );
  }

  private static ICustomParser maybeGetCustomParser() {
    String cls = GosucArg.PARSER.getValue();
    if( cls != null ) {
      try {
        Class.forName( cls ).newInstance();
      }
      catch( Exception e ) {
        throw new RuntimeException( e );
      }
    }
    return null;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy