Adding Tests for repository group handler
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java
index 8eef5b2..683ad5d 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/ArchivaRepositoryRegistry.java
@@ -157,6 +157,7 @@
         TreeSet<RepositoryValidator<? extends Repository>> val = new TreeSet<>( );
         for (RepositoryValidator<? extends Repository> validator : validators) {
             val.add( validator );
+            validator.setRepositoryRegistry( this );
         }
         return val;
     }
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/BasicRepositoryGroupValidator.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/BasicRepositoryGroupValidator.java
index e0dd00d..c84d1ec 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/BasicRepositoryGroupValidator.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/BasicRepositoryGroupValidator.java
@@ -27,6 +27,7 @@
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
+import javax.inject.Inject;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
@@ -71,18 +72,20 @@
         if ( StringUtils.isBlank( repoGroupId ) )
         {
             errors = appendError( null, "id", ISEMPTY );
-        }
-
-        if ( repoGroupId.length( ) > 100 )
+        } else
         {
-            errors = appendError( errors, "id", MAX_LENGTH_EXCEEDED, repoGroupId, Integer.toString( 100 ) );
 
-        }
+            if ( repoGroupId.length( ) > 100 )
+            {
+                errors = appendError( errors, "id", MAX_LENGTH_EXCEEDED, repoGroupId, Integer.toString( 100 ) );
 
-        Matcher matcher = REPOSITORY_ID_VALID_EXPRESSION_PATTERN.matcher( repoGroupId );
-        if ( !matcher.matches( ) )
-        {
-            errors = appendError( errors, "id", INVALID_CHARS, repoGroupId, REPOSITORY_ID_ALLOWED );
+            }
+
+            Matcher matcher = REPOSITORY_ID_VALID_EXPRESSION_PATTERN.matcher( repoGroupId );
+            if ( !matcher.matches( ) )
+            {
+                errors = appendError( errors, "id", INVALID_CHARS, repoGroupId, REPOSITORY_ID_ALLOWED );
+            }
         }
 
         if ( repositoryGroup.getMergedIndexTTL( ) <= 0 )
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/RepositoryGroupHandler.java b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/RepositoryGroupHandler.java
index c97a59e..eb8fbd3 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/RepositoryGroupHandler.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/main/java/org/apache/archiva/repository/base/group/RepositoryGroupHandler.java
@@ -56,9 +56,11 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.stream.Collectors;
 
@@ -549,7 +551,14 @@
                 setLastState( repo, RepositoryState.UNREGISTERED );
             }
         }
-
+        Iterator<RepositoryGroupConfiguration> cfgIter = configuration.getRepositoryGroups( ).iterator( );
+        while(cfgIter.hasNext()) {
+            RepositoryGroupConfiguration el = cfgIter.next( );
+            if (id.equals( el.getId() )) {
+                cfgIter.remove( );
+                break;
+            }
+        }
     }
 
     @Override
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/RepositoryGroupHandlerTest.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/RepositoryGroupHandlerTest.java
index 696cdf6..cf8de1c 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/RepositoryGroupHandlerTest.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/base/group/RepositoryGroupHandlerTest.java
@@ -18,17 +18,24 @@
  * under the License.
  */
 
+import org.apache.archiva.common.filelock.DefaultFileLockManager;
+import org.apache.archiva.common.filelock.FileLockManager;
 import org.apache.archiva.configuration.ArchivaConfiguration;
+import org.apache.archiva.configuration.Configuration;
+import org.apache.archiva.configuration.RepositoryGroupConfiguration;
 import org.apache.archiva.indexer.merger.MergedRemoteIndexesScheduler;
+import org.apache.archiva.repository.EditableRepositoryGroup;
 import org.apache.archiva.repository.Repository;
 import org.apache.archiva.repository.RepositoryException;
 import org.apache.archiva.repository.RepositoryGroup;
-import org.apache.archiva.repository.RepositoryRegistry;
 import org.apache.archiva.repository.RepositoryState;
 import org.apache.archiva.repository.RepositoryType;
 import org.apache.archiva.repository.base.ArchivaRepositoryRegistry;
 import org.apache.archiva.repository.base.ConfigurationHandler;
+import org.apache.archiva.repository.storage.fs.FilesystemStorage;
+import org.apache.archiva.repository.validation.CheckedResult;
 import org.apache.archiva.repository.validation.RepositoryValidator;
+import org.apache.archiva.repository.validation.ValidationError;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
@@ -38,10 +45,14 @@
 
 import javax.inject.Inject;
 import javax.inject.Named;
-
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.archiva.repository.validation.ErrorKeys.ISEMPTY;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
@@ -72,6 +83,7 @@
     @Inject
     ArchivaConfiguration archivaConfiguration;
 
+    Path repoBaseDir;
 
     private RepositoryGroupHandler createHandler( )
     {
@@ -80,6 +92,34 @@
         return groupHandler;
     }
 
+    private Path getRepoBaseDir() throws IOException
+    {
+        if (repoBaseDir==null) {
+            this.repoBaseDir = archivaConfiguration.getRepositoryBaseDir( ).resolve( "group" );
+            Files.createDirectories( this.repoBaseDir );
+        }
+        return repoBaseDir;
+    }
+
+
+
+    protected EditableRepositoryGroup createRepository( String id, String name, Path location ) throws IOException
+    {
+        FileLockManager lockManager = new DefaultFileLockManager();
+        FilesystemStorage storage = new FilesystemStorage(location.toAbsolutePath(), lockManager);
+        BasicRepositoryGroup repo = new BasicRepositoryGroup(id, name, storage);
+        repo.setLocation( location.toAbsolutePath().toUri());
+        return repo;
+    }
+
+    protected EditableRepositoryGroup createRepository( String id, String name) throws IOException
+    {
+        Path dir = getRepoBaseDir( ).resolve( id );
+        Files.createDirectories( dir );
+        return createRepository( id, name, dir );
+    }
+
+
     @Test
     void initializeFromConfig( )
     {
@@ -123,77 +163,180 @@
 
 
     @Test
-    void put( )
+    void put( ) throws IOException, RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        EditableRepositoryGroup repositoryGroup = createRepository( "test-group-04", "n-test-group-04" );
+        groupHandler.put( repositoryGroup );
+        RepositoryGroup storedGroup = groupHandler.get( "test-group-04" );
+        assertNotNull( storedGroup );
+        assertEquals( "test-group-04", storedGroup.getId( ) );
+        assertEquals( "n-test-group-04", storedGroup.getName( ) );
+
+        EditableRepositoryGroup repositoryGroup2 = createRepository( "test-group-04", "n2-test-group-04" );
+        groupHandler.put( repositoryGroup2 );
+        storedGroup = groupHandler.get( "test-group-04" );
+        assertNotNull( storedGroup );
+        assertEquals( "test-group-04", storedGroup.getId( ) );
+        assertEquals( "n2-test-group-04", storedGroup.getName( ) );
+
+        assertNotNull( configurationHandler.getBaseConfiguration().getRepositoryGroups( ) );
+        assertTrue( configurationHandler.getBaseConfiguration().getRepositoryGroups( ).stream( ).anyMatch( g -> g!=null && "test-group-04".equals( g.getId( ) ) ) );
     }
 
     @Test
-    void testPut( )
+    void testPut( ) throws RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
+        configuration.setId( "test-group-05" );
+        configuration.setName( "n-test-group-05" );
+        ArrayList<String> repos = new ArrayList<>( );
+        repos.add( "internal" );
+        configuration.setRepositories( repos );
+        groupHandler.put( configuration );
+
+        RepositoryGroup repo = groupHandler.get( "test-group-05" );
+        assertNotNull( repo );
+        assertEquals( "test-group-05", repo.getId( ) );
+        assertEquals( "n-test-group-05", repo.getName( ) );
+
+        assertNotNull( repo.getRepositories( ) );
+        assertEquals( 1, repo.getRepositories( ).size( ) );
+        assertEquals( "internal", repo.getRepositories( ).get( 0 ).getId( ) );
+        assertNotNull( configurationHandler.getBaseConfiguration().getRepositoryGroups( ) );
+        assertTrue( configurationHandler.getBaseConfiguration().getRepositoryGroups( ).stream( ).anyMatch( g -> g!=null && "test-group-05".equals( g.getId( ) ) ) );
     }
 
     @Test
-    void testPut1( )
+    void testPutWithoutRegister( ) throws RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        Configuration aCfg = new Configuration( );
+        RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
+        configuration.setId( "test-group-06" );
+        configuration.setName( "n-test-group-06" );
+        ArrayList<String> repos = new ArrayList<>( );
+        repos.add( "internal" );
+        configuration.setRepositories( repos );
+        groupHandler.put( configuration, aCfg );
+
+        RepositoryGroup repo = groupHandler.get( "test-group-06" );
+        assertNull( repo );
+        assertNotNull( configurationHandler.getBaseConfiguration().getRepositoryGroups( ) );
+        assertTrue( configurationHandler.getBaseConfiguration().getRepositoryGroups( ).stream( ).noneMatch( g -> g!=null && "test-group-06".equals( g.getId( ) ) ) );
+        assertTrue( aCfg.getRepositoryGroups( ).stream( ).anyMatch( g -> g!=null && "test-group-06".equals( g.getId( ) ) ) );
+
     }
 
     @Test
-    void putWithCheck( )
+    void putWithCheck( ) throws RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        BasicRepositoryGroupValidator checker = new BasicRepositoryGroupValidator( configurationHandler );
+        RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
+        configuration.setId( "" );
+        configuration.setName( "n-test-group-07" );
+        ArrayList<String> repos = new ArrayList<>( );
+        repos.add( "internal" );
+        configuration.setRepositories( repos );
+        CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.putWithCheck( configuration, checker );
+        assertNull( groupHandler.get( "test-group-07" ) );
+        assertNotNull( result.getResult( ) );
+        assertNotNull( result.getResult( ).get( "id" ) );
+        assertEquals( 1, result.getResult( ).get( "id" ).size( ) );
+        assertEquals( ISEMPTY, result.getResult( ).get( "id" ).get( 0 ).getType( ) );
     }
 
     @Test
-    void remove( )
+    void remove( ) throws RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
+        configuration.setId( "test-group-08" );
+        configuration.setName( "n-test-group-08" );
+        groupHandler.put( configuration );
+        assertNotNull( groupHandler.get( "test-group-08" ) );
+        groupHandler.remove( "test-group-08" );
+        assertNull( groupHandler.get( "test-group-08" ) );
     }
 
     @Test
-    void testRemove( )
+    void testRemove( ) throws RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        Configuration aCfg = new Configuration( );
+        RepositoryGroupConfiguration configuration = new RepositoryGroupConfiguration( );
+        configuration.setId( "test-group-09" );
+        configuration.setName( "n-test-group-09" );
+        ArrayList<String> repos = new ArrayList<>( );
+        repos.add( "internal" );
+        configuration.setRepositories( repos );
+        groupHandler.put( configuration, aCfg );
+        assertTrue( aCfg.getRepositoryGroups( ).stream( ).anyMatch( g -> g != null && "test-group-09".equals( g.getId( ) ) ) );
+        groupHandler.remove( "test-group-09", aCfg );
+        assertNull( groupHandler.get( "test-group-09" ) );
+        assertTrue( aCfg.getRepositoryGroups( ).stream( ).noneMatch( g -> g != null && "test-group-09".equals( g.getId( ) ) ) );
+        assertNull( groupHandler.get( "test-group-09" ) );
+
+    }
+
+
+    @Test
+    void validateRepository( ) throws IOException
+    {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        EditableRepositoryGroup repositoryGroup = createRepository( "test-group-10", "n-test-group-10" );
+        repositoryGroup.setMergedIndexTTL( 5 );
+        CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepository( repositoryGroup );
+        assertNotNull( result );
+        assertEquals( 0, result.getResult( ).size( ) );
+
+        repositoryGroup = createRepository( "test-group-10", "n-test-group-10###" );
+        result = groupHandler.validateRepository( repositoryGroup );
+        assertNotNull( result );
+        assertEquals( 2, result.getResult( ).size( ) );
+        assertNotNull( result.getResult().get( "merged_index_ttl" ) );
+        assertNotNull( result.getResult().get( "name" ) );
+
     }
 
     @Test
-    void get( )
+    void validateRepositoryIfExisting( ) throws IOException, RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        EditableRepositoryGroup repositoryGroup = createRepository( "test-group-11", "n-test-group-11" );
+        repositoryGroup.setMergedIndexTTL( 5 );
+        groupHandler.put( repositoryGroup );
+        CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepository( repositoryGroup );
+        assertNotNull( result );
+        assertEquals( 1, result.getResult( ).size( ) );
+
+
     }
 
     @Test
-    void testClone( )
+    void validateRepositoryForUpdate( ) throws IOException, RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        EditableRepositoryGroup repositoryGroup = createRepository( "test-group-12", "n-test-group-12" );
+        repositoryGroup.setMergedIndexTTL( 5 );
+        groupHandler.put( repositoryGroup );
+        CheckedResult<RepositoryGroup, Map<String, List<ValidationError>>> result = groupHandler.validateRepositoryForUpdate( repositoryGroup );
+        assertNotNull( result );
+        assertEquals( 0, result.getResult( ).size( ) );
+
     }
 
     @Test
-    void updateReferences( )
+    void has( ) throws IOException, RepositoryException
     {
+        RepositoryGroupHandler groupHandler = createHandler( );
+        EditableRepositoryGroup repositoryGroup = createRepository( "test-group-13", "n-test-group-13" );
+        repositoryGroup.setMergedIndexTTL( 5 );
+        assertFalse( groupHandler.hasRepository( "test-group-13" ) );
+        groupHandler.put( repositoryGroup );
+        assertTrue( groupHandler.hasRepository( "test-group-13" ) );
     }
 
-    @Test
-    void getAll( )
-    {
-    }
-
-    @Test
-    void getValidator( )
-    {
-    }
-
-    @Test
-    void validateRepository( )
-    {
-    }
-
-    @Test
-    void validateRepositoryForUpdate( )
-    {
-    }
-
-    @Test
-    void has( )
-    {
-    }
-
-    @Test
-    void close( )
-    {
-    }
 }
\ No newline at end of file
diff --git a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
index 5a4c9f5..5a3a473 100644
--- a/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
+++ b/archiva-modules/archiva-base/archiva-repository-layer/src/test/java/org/apache/archiva/repository/mock/RepositoryProviderMock.java
@@ -43,6 +43,7 @@
 import java.time.Period;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Just a simple mock class for the repository provider
@@ -248,7 +249,19 @@
 
     @Override
     public RepositoryGroupConfiguration getRepositoryGroupConfiguration(RepositoryGroup repositoryGroup) throws RepositoryException {
-        return null;
+        RepositoryGroupConfiguration cfg = new RepositoryGroupConfiguration();
+        cfg.setId(repositoryGroup.getId());
+        cfg.setName(repositoryGroup.getName());
+        if (repositoryGroup.supportsFeature( IndexCreationFeature.class ))
+        {
+            IndexCreationFeature indexCreationFeature = repositoryGroup.getFeature( IndexCreationFeature.class ).get();
+
+            cfg.setMergedIndexPath( indexCreationFeature.getIndexPath().toString() );
+        }
+        cfg.setMergedIndexTtl(repositoryGroup.getMergedIndexTTL());
+        cfg.setRepositories(repositoryGroup.getRepositories().stream().map( Repository::getId ).collect( Collectors.toList()));
+        cfg.setCronExpression(repositoryGroup.getSchedulingDefinition());
+        return cfg;
     }
 
     @Override