You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2016/11/28 16:07:54 UTC

[09/14] zest-java git commit: classscanner: prever Streams over Iterables

classscanner: prever Streams over Iterables


Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/3acd801d
Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/3acd801d
Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/3acd801d

Branch: refs/heads/develop
Commit: 3acd801d4a51ca16a0db4b91531842db81261633
Parents: 611ef1b
Author: Paul Merlin <pa...@apache.org>
Authored: Mon Nov 28 11:12:55 2016 +0100
Committer: Paul Merlin <pa...@apache.org>
Committed: Mon Nov 28 11:28:41 2016 +0100

----------------------------------------------------------------------
 .../org/apache/zest/bootstrap/ClassScanner.java | 160 +++++++------------
 .../apache/zest/bootstrap/ClassScannerTest.java |  14 +-
 .../builder/ApplicationBuilderTest.java         |  12 +-
 .../runtime/query/IterableQuerySourceTest.java  |   8 +-
 .../library/rest/common/ValueAssembler.java     |  12 +-
 .../server/assembler/RestServerAssembler.java   |  32 ++--
 6 files changed, 98 insertions(+), 140 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-java/blob/3acd801d/core/bootstrap/src/main/java/org/apache/zest/bootstrap/ClassScanner.java
----------------------------------------------------------------------
diff --git a/core/bootstrap/src/main/java/org/apache/zest/bootstrap/ClassScanner.java b/core/bootstrap/src/main/java/org/apache/zest/bootstrap/ClassScanner.java
index 7b8cd6b..c792048 100644
--- a/core/bootstrap/src/main/java/org/apache/zest/bootstrap/ClassScanner.java
+++ b/core/bootstrap/src/main/java/org/apache/zest/bootstrap/ClassScanner.java
@@ -25,47 +25,46 @@ import java.lang.reflect.Modifier;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.security.CodeSource;
+import java.util.Collections;
+import java.util.List;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.regex.Pattern;
-import org.apache.zest.functional.Iterables;
-
-import static org.apache.zest.functional.Iterables.filter;
-import static org.apache.zest.functional.Iterables.flatten;
-import static org.apache.zest.functional.Iterables.flattenIterables;
-import static org.apache.zest.functional.Iterables.iterable;
-import static org.apache.zest.functional.Iterables.map;
+import java.util.stream.Stream;
 
 /**
  * Scan classpath for classes that matches given criteria. Useful for automated assemblies with lots of similar classes.
  */
 public class ClassScanner
 {
+    private static final ValidClass VALID_CLASS_PREDICATE = new ValidClass();
+
     /**
      * Get all classes from the same package of the given class, and recursively in all subpackages.
      * <p>
      * This only works if the seed class is loaded from a file: URL. Jar files are possible as well. Abstract classes
-     * are not included in the results. For further filtering use e.g. Iterables.filter.
+     * are not included in the results. For further filtering use e.g. Stream.filter.
      * </p>
      * @param seedClass starting point for classpath scanning
      *
-     * @return iterable of all concrete classes in the same package as the seedclass, and also all classes in subpackages.
+     * @return Stream of all concrete classes in the same package as the seedclass, and also all classes in subpackages.
      */
-    public static Iterable<Class<?>> findClasses( final Class<?> seedClass )
+    public static Stream<? extends Class<?>> findClasses( final Class<?> seedClass )
     {
         CodeSource codeSource = seedClass.getProtectionDomain().getCodeSource();
         if( codeSource == null )
         {
-            return Iterables.empty();
+            return Stream.of();
         }
 
         URL location = codeSource.getLocation();
 
         if( !location.getProtocol().equals( "file" ) )
         {
-            throw new IllegalArgumentException( "Can only enumerate classes from file system locations. URL is:" + location );
+            throw new IllegalArgumentException(
+                "Can only enumerate classes from file system locations. URL is:" + location );
         }
 
         final File file;
@@ -75,7 +74,8 @@ public class ClassScanner
         }
         catch( URISyntaxException e )
         {
-            throw new IllegalArgumentException( "The file location of codebase is invalid. Can not convert to URI. URL is:" + location );
+            throw new IllegalArgumentException(
+                "The file location of codebase is invalid. Can not convert to URI. URL is:" + location );
         }
 
         if( file.getName().endsWith( ".jar" ) )
@@ -85,38 +85,27 @@ public class ClassScanner
                 final String packageName = seedClass.getPackage().getName().replace( '.', '/' );
 
                 JarFile jarFile = new JarFile( file );
-                Iterable<JarEntry> entries = Iterables.iterable( jarFile.entries() );
+                List<JarEntry> entries = Collections.list( jarFile.entries() );
                 try
                 {
-                    return Iterables.toList( filter( new ValidClass(),
-                                                     map( new Function<JarEntry, Class<?>>()
-                                                     {
-                                                         @Override
-                                                         public Class apply( JarEntry jarEntry )
-                                                         {
-                                                             String name = jarEntry.getName();
-                                                             name = name.substring( 0, name.length() - 6 );
-                                                             name = name.replace( '/', '.' );
-                                                             try
-                                                             {
-                                                                 return seedClass.getClassLoader().loadClass( name );
-                                                             }
-                                                             catch( ClassNotFoundException e )
-                                                             {
-                                                                 return null;
-                                                             }
-                                                         }
-                                                     }
-                                                         , filter( new Predicate<JarEntry>()
-                                                     {
-                                                         @Override
-                                                         public boolean test( JarEntry jarEntry )
-                                                         {
-                                                             return jarEntry.getName()
-                                                                        .startsWith( packageName ) && jarEntry.getName()
-                                                                 .endsWith( ".class" );
-                                                         }
-                                                     }, entries ) ) ) );
+                    return entries.stream()
+                                  .filter( jarEntry -> jarEntry.getName().startsWith( packageName )
+                                                       && jarEntry.getName().endsWith( ".class" ) )
+                                  .map( jarEntry ->
+                                        {
+                                            String name = jarEntry.getName();
+                                            name = name.substring( 0, name.length() - 6 );
+                                            name = name.replace( '/', '.' );
+                                            try
+                                            {
+                                                return seedClass.getClassLoader().loadClass( name );
+                                            }
+                                            catch( ClassNotFoundException e )
+                                            {
+                                                return null;
+                                            }
+                                        } )
+                                  .filter( VALID_CLASS_PREDICATE );
                 }
                 finally
                 {
@@ -131,34 +120,22 @@ public class ClassScanner
         else
         {
             final File path = new File( file, seedClass.getPackage().getName().replace( '.', File.separatorChar ) );
-            Iterable<File> files = findFiles( path, new Predicate<File>()
-            {
-                @Override
-                public boolean test( File file )
-                {
-                    return file.getName().endsWith( ".class" );
-                }
-            } );
-
-            return filter( new ValidClass(),
-                           map( new Function<File, Class<?>>()
-                           {
-                               @Override
-                               public Class<?> apply( File f )
-                               {
-                                   String fileName = f.getAbsolutePath().substring( file.toString().length() + 1 );
-                                   fileName = fileName.replace( File.separatorChar, '.' )
-                                       .substring( 0, fileName.length() - 6 );
-                                   try
-                                   {
-                                       return seedClass.getClassLoader().loadClass( fileName );
-                                   }
-                                   catch( ClassNotFoundException e )
-                                   {
-                                       return null;
-                                   }
-                               }
-                           }, files ) );
+            Stream<File> classFiles = findFiles( path, candidate -> candidate.getName().endsWith( ".class" ) );
+            return classFiles
+                .map( classFile ->
+                      {
+                          String fileName = classFile.getAbsolutePath().substring( file.toString().length() + 1 );
+                          fileName = fileName.replace( File.separatorChar, '.' ).substring( 0, fileName.length() - 6 );
+                          try
+                          {
+                              return seedClass.getClassLoader().loadClass( fileName );
+                          }
+                          catch( ClassNotFoundException e )
+                          {
+                              return null;
+                          }
+                      } )
+                .filter( VALID_CLASS_PREDICATE );
         }
     }
 
@@ -175,35 +152,21 @@ public class ClassScanner
     public static Predicate<Class<?>> matches( String regex )
     {
         final Pattern pattern = Pattern.compile( regex );
-
-        return new Predicate<Class<?>>()
-        {
-            @Override
-            public boolean test( Class<?> aClass )
-            {
-                return pattern.matcher( aClass.getName() ).matches();
-            }
-        };
+        return aClass -> pattern.matcher( aClass.getName() ).matches();
     }
 
-    private static Iterable<File> findFiles( File directory, final Predicate<File> filter )
+    private static Stream<File> findFiles( File directory, final Predicate<File> filter )
     {
-        return flatten( filter( filter, iterable( directory.listFiles() ) ),
-                        flattenIterables( map( new Function<File, Iterable<File>>()
-                        {
-                            @Override
-                            public Iterable<File> apply( File file )
-                            {
-                                return findFiles( file, filter );
-                            }
-                        }, filter( new Predicate<File>()
-                        {
-                            @Override
-                            public boolean test( File file )
-                            {
-                                return file.isDirectory();
-                            }
-                        }, iterable( directory.listFiles() ) ) ) ) );
+        File[] listedFiles = directory.listFiles();
+        if( listedFiles == null )
+        {
+            return Stream.of();
+        }
+        return Stream.concat( Stream.of( listedFiles ).filter( filter ),
+                              Stream.of( listedFiles )
+                                    .filter( File::isDirectory )
+                                    .map( dir -> findFiles( dir, filter ) )
+                                    .flatMap( Function.identity() ) );
     }
 
     private static class ValidClass
@@ -212,7 +175,8 @@ public class ClassScanner
         @Override
         public boolean test( Class<?> item )
         {
-            return ( item.isInterface() || !Modifier.isAbstract( item.getModifiers() ) ) && ( !item.isEnum() && !item.isAnonymousClass() );
+            return ( item.isInterface() || !Modifier.isAbstract( item.getModifiers() ) )
+                   && ( !item.isEnum() && !item.isAnonymousClass() );
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/zest-java/blob/3acd801d/core/bootstrap/src/test/java/org/apache/zest/bootstrap/ClassScannerTest.java
----------------------------------------------------------------------
diff --git a/core/bootstrap/src/test/java/org/apache/zest/bootstrap/ClassScannerTest.java b/core/bootstrap/src/test/java/org/apache/zest/bootstrap/ClassScannerTest.java
index 0a9932b..bb38ff5 100644
--- a/core/bootstrap/src/test/java/org/apache/zest/bootstrap/ClassScannerTest.java
+++ b/core/bootstrap/src/test/java/org/apache/zest/bootstrap/ClassScannerTest.java
@@ -19,16 +19,14 @@
  */
 package org.apache.zest.bootstrap;
 
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.bootstrap.somepackage.Test2Value;
 import org.apache.zest.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
 import org.junit.Assert;
 import org.junit.Test;
-import org.apache.zest.api.activation.ActivationException;
-import org.apache.zest.bootstrap.somepackage.Test2Value;
-import org.apache.zest.functional.Iterables;
 
 import static org.apache.zest.bootstrap.ClassScanner.findClasses;
 import static org.apache.zest.bootstrap.ClassScanner.matches;
-import static org.apache.zest.functional.Iterables.filter;
 
 /**
  * Test and showcase of the ClassScanner assembly utility.
@@ -48,10 +46,8 @@ public class ClassScannerTest
                 new DefaultUnitOfWorkAssembler().assemble( module );
 
                 // Find all classes starting from TestValue, but include only the ones that are named *Value
-                for( Class aClass : filter( matches( ".*Value" ), findClasses( TestValue.class ) ) )
-                {
-                    module.values( aClass );
-                }
+                findClasses( TestValue.class ).filter( matches( ".*Value" ) )
+                                              .forEach( module::values );
             }
         };
 
@@ -62,6 +58,6 @@ public class ClassScannerTest
     @Test
     public void testClassScannerJar()
     {
-        Assert.assertEquals( 185, Iterables.count( findClasses( Test.class ) ) );
+        Assert.assertEquals( 185, findClasses( Test.class ).count() );
     }
 }

http://git-wip-us.apache.org/repos/asf/zest-java/blob/3acd801d/core/bootstrap/src/test/java/org/apache/zest/bootstrap/builder/ApplicationBuilderTest.java
----------------------------------------------------------------------
diff --git a/core/bootstrap/src/test/java/org/apache/zest/bootstrap/builder/ApplicationBuilderTest.java b/core/bootstrap/src/test/java/org/apache/zest/bootstrap/builder/ApplicationBuilderTest.java
index fea47d4..a07d92a 100644
--- a/core/bootstrap/src/test/java/org/apache/zest/bootstrap/builder/ApplicationBuilderTest.java
+++ b/core/bootstrap/src/test/java/org/apache/zest/bootstrap/builder/ApplicationBuilderTest.java
@@ -22,8 +22,6 @@ package org.apache.zest.bootstrap.builder;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import org.json.JSONException;
-import org.junit.Test;
 import org.apache.zest.api.activation.ActivationException;
 import org.apache.zest.api.mixin.Mixins;
 import org.apache.zest.api.structure.Application;
@@ -31,12 +29,15 @@ import org.apache.zest.api.structure.Module;
 import org.apache.zest.bootstrap.Assembler;
 import org.apache.zest.bootstrap.AssemblyException;
 import org.apache.zest.bootstrap.ModuleAssembly;
+import org.json.JSONException;
+import org.junit.Test;
 
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
+import static java.util.stream.Collectors.toList;
 import static org.apache.zest.bootstrap.ClassScanner.findClasses;
 import static org.apache.zest.bootstrap.ClassScanner.matches;
 import static org.apache.zest.functional.Iterables.filter;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
 
 public class ApplicationBuilderTest
 {
@@ -48,7 +49,8 @@ public class ApplicationBuilderTest
         builder.withLayer( "layer1" ).using( "layer2" ).using( "layer3" );
         builder.withLayer( "layer2" );
         builder.withLayer( "layer3" ).withModule( "test module" ).
-            withAssemblers( filter( matches( ".*ServiceAssembler" ), findClasses( getClass() ) ) );
+            withAssemblers( filter( matches( ".*ServiceAssembler" ),
+                                    findClasses( getClass() ).collect( toList() ) ) );
         Application application = builder.newApplication();
         Module module = application.findModule( "layer3", "test module" );
         TestService service = module.findService( TestService.class ).get();

http://git-wip-us.apache.org/repos/asf/zest-java/blob/3acd801d/core/runtime/src/test/java/org/apache/zest/runtime/query/IterableQuerySourceTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/zest/runtime/query/IterableQuerySourceTest.java b/core/runtime/src/test/java/org/apache/zest/runtime/query/IterableQuerySourceTest.java
index 2b35c48..d36e659 100644
--- a/core/runtime/src/test/java/org/apache/zest/runtime/query/IterableQuerySourceTest.java
+++ b/core/runtime/src/test/java/org/apache/zest/runtime/query/IterableQuerySourceTest.java
@@ -81,15 +81,11 @@ public class IterableQuerySourceTest
     {
         SingletonAssembler assembler = new SingletonAssembler()
         {
+            @Override
             public void assemble( ModuleAssembly module )
                 throws AssemblyException
             {
-                Iterable<Class<?>> entities = ClassScanner.findClasses( DomainEntity.class );
-
-                for( Class entity : entities )
-                {
-                    module.entities( entity );
-                }
+                ClassScanner.findClasses( DomainEntity.class ).forEach( module::entities );
 
                 module.values( ContactsValue.class, ContactValue.class );
                 new EntityTestAssembler().assemble( module );

http://git-wip-us.apache.org/repos/asf/zest-java/blob/3acd801d/libraries/rest-common/src/main/java/org/apache/zest/library/rest/common/ValueAssembler.java
----------------------------------------------------------------------
diff --git a/libraries/rest-common/src/main/java/org/apache/zest/library/rest/common/ValueAssembler.java b/libraries/rest-common/src/main/java/org/apache/zest/library/rest/common/ValueAssembler.java
index f8a301e..8cebeba 100644
--- a/libraries/rest-common/src/main/java/org/apache/zest/library/rest/common/ValueAssembler.java
+++ b/libraries/rest-common/src/main/java/org/apache/zest/library/rest/common/ValueAssembler.java
@@ -26,9 +26,8 @@ import org.apache.zest.bootstrap.Assembler;
 import org.apache.zest.bootstrap.AssemblyException;
 import org.apache.zest.bootstrap.ModuleAssembly;
 
-import static org.apache.zest.api.util.Classes.*;
-import static org.apache.zest.bootstrap.ClassScanner.*;
-import static org.apache.zest.functional.Iterables.*;
+import static org.apache.zest.api.util.Classes.isAssignableFrom;
+import static org.apache.zest.bootstrap.ClassScanner.findClasses;
 
 /**
  * Assembler for all REST values.
@@ -40,9 +39,8 @@ public class ValueAssembler
     public void assemble( ModuleAssembly module )
         throws AssemblyException
     {
-        for( Class<?> aClass : filter( isAssignableFrom( ValueComposite.class ), findClasses( Resource.class ) ))
-        {
-            module.values( aClass ).visibleIn( Visibility.application );
-        }
+        findClasses( Resource.class ).filter( isAssignableFrom( ValueComposite.class ) )
+                                     .forEach( resourceType -> module.values( resourceType )
+                                                                     .visibleIn( Visibility.application ) );
     }
 }

http://git-wip-us.apache.org/repos/asf/zest-java/blob/3acd801d/libraries/rest-server/src/main/java/org/apache/zest/library/rest/server/assembler/RestServerAssembler.java
----------------------------------------------------------------------
diff --git a/libraries/rest-server/src/main/java/org/apache/zest/library/rest/server/assembler/RestServerAssembler.java b/libraries/rest-server/src/main/java/org/apache/zest/library/rest/server/assembler/RestServerAssembler.java
index a9ee8ac..d51c8d5 100644
--- a/libraries/rest-server/src/main/java/org/apache/zest/library/rest/server/assembler/RestServerAssembler.java
+++ b/libraries/rest-server/src/main/java/org/apache/zest/library/rest/server/assembler/RestServerAssembler.java
@@ -23,6 +23,7 @@ package org.apache.zest.library.rest.server.assembler;
 import freemarker.template.Configuration;
 import freemarker.template.Version;
 import java.lang.reflect.Modifier;
+import java.util.List;
 import java.util.Properties;
 import java.util.function.Predicate;
 import org.apache.velocity.app.VelocityEngine;
@@ -42,11 +43,11 @@ import org.apache.zest.library.rest.server.restlet.responsewriter.DefaultRespons
 import org.apache.zest.library.rest.server.spi.ResponseWriter;
 import org.restlet.service.MetadataService;
 
+import static java.util.stream.Collectors.toList;
 import static org.apache.zest.api.util.Classes.hasModifier;
 import static org.apache.zest.api.util.Classes.isAssignableFrom;
 import static org.apache.zest.bootstrap.ImportedServiceDeclaration.INSTANCE;
 import static org.apache.zest.bootstrap.ImportedServiceDeclaration.NEW_OBJECT;
-import static org.apache.zest.functional.Iterables.filter;
 
 /**
  * JAVADOC
@@ -66,7 +67,7 @@ public class RestServerAssembler
             VelocityEngine velocity = new VelocityEngine( props );
 
             module.importedServices( VelocityEngine.class )
-                .importedBy( INSTANCE ).setMetaInfo( velocity );
+                  .importedBy( INSTANCE ).setMetaInfo( velocity );
         }
         catch( Exception e )
         {
@@ -83,28 +84,29 @@ public class RestServerAssembler
         module.importedServices( MetadataService.class );
 
         module.importedServices( ResponseWriterDelegator.class )
-            .identifiedBy( "responsewriterdelegator" )
-            .importedBy( NEW_OBJECT )
-            .visibleIn( Visibility.layer );
+              .identifiedBy( "responsewriterdelegator" )
+              .importedBy( NEW_OBJECT )
+              .visibleIn( Visibility.layer );
         module.objects( ResponseWriterDelegator.class );
 
         module.importedServices( RequestReaderDelegator.class )
-            .identifiedBy( "requestreaderdelegator" )
-            .importedBy( NEW_OBJECT )
-            .visibleIn( Visibility.layer );
+              .identifiedBy( "requestreaderdelegator" )
+              .importedBy( NEW_OBJECT )
+              .visibleIn( Visibility.layer );
         module.objects( RequestReaderDelegator.class );
 
-        module.importedServices( InteractionConstraintsService.class ).
-            importedBy( NewObjectImporter.class ).
-            visibleIn( Visibility.application );
+        module.importedServices( InteractionConstraintsService.class )
+              .importedBy( NewObjectImporter.class )
+              .visibleIn( Visibility.application );
         module.objects( InteractionConstraintsService.class );
 
         // Standard response writers
-        Iterable<Class<?>> writers = ClassScanner.findClasses( DefaultResponseWriter.class );
-        Predicate<Class<?>> responseWriterClass = isAssignableFrom( ResponseWriter.class );
+        Predicate<Class<?>> isResponseWriterClass = isAssignableFrom( ResponseWriter.class );
         Predicate<Class<?>> isNotAnAbstract = hasModifier( Modifier.ABSTRACT ).negate();
-        Iterable<Class<?>> candidates = filter( isNotAnAbstract.and( responseWriterClass ), writers );
-        for( Class<?> responseWriter : candidates )
+        List<? extends Class<?>> responseWriters = ClassScanner.findClasses( DefaultResponseWriter.class )
+                                                               .filter( isNotAnAbstract.and( isResponseWriterClass ) )
+                                                               .collect( toList() );
+        for( Class<?> responseWriter : responseWriters )
         {
             module.objects( responseWriter );
         }