]> source.dussan.org Git - archiva.git/commitdiff
[MRM-1390] Implement search methods for generic metadata and properties in Cassandra...
authorCarlos Sanchez <carlos@apache.org>
Sun, 23 Nov 2014 10:34:24 +0000 (11:34 +0100)
committerCarlos Sanchez <carlos@apache.org>
Mon, 1 Dec 2014 15:48:31 +0000 (16:48 +0100)
Some caveats with Cassandra implementation:

We can't search artifacts by any (wildcard) property, so searchArtifacts(text,...) just calls getArtifactsByMetadata
The exact parameter is ignored as we can't do non exact searches in Cassandra

archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepository.java
archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/CassandraUtils.java
archiva-modules/plugins/metadata-store-cassandra/src/main/java/org/apache/archiva/metadata/repository/cassandra/model/MetadataFacetModel.java
archiva-modules/plugins/metadata-store-cassandra/src/test/java/org/apache/archiva/metadata/repository/cassandra/CassandraMetadataRepositoryTest.java
archiva-modules/plugins/metadata-store-jcr/src/main/java/org/apache/archiva/metadata/repository/jcr/JcrMetadataRepository.java

index 779c19f1c546d47d3514c2decd35b64fa00367c3..268fd157ecc56464feda8fac6b89c869f441d8eb 100644 (file)
@@ -77,6 +77,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -1826,25 +1827,114 @@ public class CassandraMetadataRepository
         return artifactMetadataMap.values();
     }
 
+    /**
+     * Project version and artifact level metadata are stored in the same place, no distinctions in Cassandra
+     * implementation, just calls {@link #getArtifactsByMetadata(String, String, String)}
+     */
     @Override
     public List<ArtifactMetadata> getArtifactsByProjectVersionMetadata( String key, String value, String repositoryId )
         throws MetadataRepositoryException
     {
-        throw new UnsupportedOperationException( "not yet implemented in Cassandra backend" );
+        return getArtifactsByMetadata( key, value, repositoryId );
     }
 
     @Override
     public List<ArtifactMetadata> getArtifactsByMetadata( String key, String value, String repositoryId )
         throws MetadataRepositoryException
     {
-        throw new UnsupportedOperationException( "not yet implemented in Cassandra backend" );
+        RangeSlicesQuery<String, String, String> query =
+            HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
+            .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
+            .setColumnNames( MetadataFacetModel.COLUMNS ) //
+            .addEqualsExpression( VALUE.toString(), value );
+
+        if ( key != null )
+        {
+            query.addEqualsExpression( KEY.toString(), key ); //
+        }
+        if ( repositoryId != null )
+        {
+            query.addEqualsExpression( "repositoryName", repositoryId );
+        }
+
+        QueryResult<OrderedRows<String, String, String>> metadataFacetResult = query.execute();
+        if ( metadataFacetResult.get() == null || metadataFacetResult.get().getCount() < 1 )
+        {
+            return Collections.emptyList();
+        }
+
+        List<ArtifactMetadata> artifactMetadatas = new LinkedList<ArtifactMetadata>();
+
+        // TODO doing multiple queries, there should be a way to get all the artifactMetadatas for any number of
+        // projects
+        for ( Row<String, String, String> row : metadataFacetResult.get() )
+        {
+            QueryResult<OrderedRows<String, String, String>> artifactMetadataResult =
+                HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
+                .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
+                .setColumnNames( ArtifactMetadataModel.COLUMNS ) //
+                .setRowCount( Integer.MAX_VALUE ) //
+                .addEqualsExpression( REPOSITORY_NAME.toString(),
+                                      getStringValue( row.getColumnSlice(), REPOSITORY_NAME ) ) //
+                .addEqualsExpression( NAMESPACE_ID.toString(), getStringValue( row.getColumnSlice(), NAMESPACE_ID ) ) //
+                .addEqualsExpression( PROJECT.toString(), getStringValue( row.getColumnSlice(), PROJECT_ID ) ) //
+                .addEqualsExpression( PROJECT_VERSION.toString(),
+                                      getStringValue( row.getColumnSlice(), PROJECT_VERSION ) ) //
+                .execute();
+
+            if ( artifactMetadataResult.get() == null || artifactMetadataResult.get().getCount() < 1 )
+            {
+                return Collections.emptyList();
+            }
+
+            for ( Row<String, String, String> artifactMetadataRow : artifactMetadataResult.get() )
+            {
+                artifactMetadatas.add( mapArtifactMetadataStringColumnSlice( artifactMetadataRow.getColumnSlice() ) );
+            }
+        }
+
+        return mapArtifactMetadataToArtifact( metadataFacetResult, artifactMetadatas );
     }
 
     @Override
     public List<ArtifactMetadata> getArtifactsByProperty( String key, String value, String repositoryId )
         throws MetadataRepositoryException
     {
-        throw new UnsupportedOperationException( "getArtifactsByProperty not yet implemented in Cassandra backend" );
+        QueryResult<OrderedRows<String, String, String>> result =
+            HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
+            .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
+            .setColumnNames( PROJECT_ID.toString(), REPOSITORY_NAME.toString(), NAMESPACE_ID.toString(),
+                             PROJECT_VERSION.toString() ) //
+            .addEqualsExpression( key, value ) //
+            .execute();
+
+        int count = result.get().getCount();
+
+        if ( count < 1 )
+        {
+            return Collections.emptyList();
+        }
+
+        List<ArtifactMetadata> artifacts = new LinkedList<ArtifactMetadata>();
+
+        for ( Row<String, String, String> row : result.get() )
+        {
+            // TODO doing multiple queries, there should be a way to get all the artifactMetadatas for any number of
+            // projects
+            try
+            {
+                artifacts.addAll( getArtifacts( getStringValue( row.getColumnSlice(), REPOSITORY_NAME ),
+                                                getStringValue( row.getColumnSlice(), NAMESPACE_ID ),
+                                                getStringValue( row.getColumnSlice(), PROJECT_ID ),
+                                                getStringValue( row.getColumnSlice(), PROJECT_VERSION ) ) );
+            }
+            catch ( MetadataResolutionException e )
+            {
+                // never raised
+                throw new IllegalStateException( e );
+            }
+        }
+        return artifacts;
     }
 
     @Override
@@ -2046,29 +2136,12 @@ public class CassandraMetadataRepository
 
         for ( Row<String, String, String> row : result.get() )
         {
-            ColumnSlice<String, String> columnSlice = row.getColumnSlice();
-            ArtifactMetadata artifactMetadata = new ArtifactMetadata();
-            artifactMetadata.setNamespace( getStringValue( columnSlice, NAMESPACE_ID.toString() ) );
-            artifactMetadata.setSize( getAsLongValue( columnSlice, SIZE.toString() ) );
-            artifactMetadata.setId( getStringValue( columnSlice, ID.toString() ) );
-            artifactMetadata.setFileLastModified( getAsLongValue( columnSlice, FILE_LAST_MODIFIED.toString() ) );
-            artifactMetadata.setMd5( getStringValue( columnSlice, MD5.toString() ) );
-            artifactMetadata.setProject( getStringValue( columnSlice, PROJECT.toString() ) );
-            artifactMetadata.setProjectVersion( getStringValue( columnSlice, PROJECT_VERSION.toString() ) );
-            artifactMetadata.setRepositoryId( repoId );
-            artifactMetadata.setSha1( getStringValue( columnSlice, SHA1.toString() ) );
-            artifactMetadata.setVersion( getStringValue( columnSlice, VERSION.toString() ) );
-            Long whenGathered = getAsLongValue( columnSlice, WHEN_GATHERED.toString() );
-            if ( whenGathered != null )
-            {
-                artifactMetadata.setWhenGathered( new Date( whenGathered ) );
-            }
-            artifactMetadatas.add( artifactMetadata );
+            artifactMetadatas.add( mapArtifactMetadataStringColumnSlice( row.getColumnSlice() ) );
         }
 
         result = HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
-            .setColumnNames( FACET_ID.toString(), NAME.toString(), VALUE.toString(), KEY.toString(), PROJECT_VERSION.toString() ) //
+            .setColumnNames( MetadataFacetModel.COLUMNS ) //
             .setRowCount( Integer.MAX_VALUE ) //
             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
@@ -2076,6 +2149,13 @@ public class CassandraMetadataRepository
             .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion ) //
             .execute();
 
+        return mapArtifactMetadataToArtifact(result, artifactMetadatas);
+    }
+
+    /**
+     * Attach metadata to each of the  ArtifactMetadata objects
+     */
+    private List<ArtifactMetadata> mapArtifactMetadataToArtifact(QueryResult<OrderedRows<String, String, String>> result, List<ArtifactMetadata> artifactMetadatas) {
         if ( result.get() == null || result.get().getCount() < 1 )
         {
             return artifactMetadatas;
@@ -2147,8 +2227,6 @@ public class CassandraMetadataRepository
                     }
                 }
             }
-
-
         }
 
         return artifactMetadatas;
@@ -2198,17 +2276,28 @@ public class CassandraMetadataRepository
         return ModelMapperHolder.MODEL_MAPPER;
     }
 
+    /**
+     * This implementation just calls getArtifactsByMetadata( null, text, repositoryId ). We can't search artifacts by
+     * any property.
+     */
     @Override
     public List<ArtifactMetadata> searchArtifacts( String text, String repositoryId, boolean exact )
         throws MetadataRepositoryException
     {
-        throw new UnsupportedOperationException( "searchArtifacts not yet implemented in Cassandra backend" );
+        return getArtifactsByMetadata( null, text, repositoryId );
     }
 
+    /**
+     * The exact parameter is ignored as we can't do non exact searches in Cassandra
+     */
     @Override
     public List<ArtifactMetadata> searchArtifacts( String key, String text, String repositoryId, boolean exact )
         throws MetadataRepositoryException
     {
-        throw new UnsupportedOperationException( "searchArtifacts not yet implemented in Cassandra backend" );
+        // TODO optimize
+        List<ArtifactMetadata> artifacts = new LinkedList<ArtifactMetadata>();
+        artifacts.addAll( getArtifactsByMetadata( key, text, repositoryId ) );
+        artifacts.addAll( getArtifactsByProperty( key, text, repositoryId ) );
+        return artifacts;
     }
 }
index 6366fe9f8d51b1a8291f6742f60c21fdfa7670fe..f3de42b9053fe8d0cf55e00222b861ef3b66f0f5 100644 (file)
@@ -95,18 +95,18 @@ public class CassandraUtils
         return hColumn == null ? null : hColumn.getValue();
     }
 
-    public static Long getLongValue( ColumnSlice<String, Long> columnSlice, String columnName )
+    public static Long getLongValue( ColumnSlice<String, ?> columnSlice, String columnName )
     {
         if ( StringUtils.isEmpty( columnName ) )
         {
             return null;
         }
 
-        HColumn<String, Long> hColumn = columnSlice.getColumnByName( columnName );
+        HColumn<String, Long> hColumn = (HColumn<String, Long>) columnSlice.getColumnByName( columnName );
         return hColumn == null ? null : hColumn.getValue();
     }
 
-    public static String getAsStringValue( ColumnSlice<String, Long> columnSlice, String columnName )
+    public static <T> String getAsStringValue( ColumnSlice<String, T> columnSlice, String columnName )
     {
         StringSerializer ss = StringSerializer.get();
         if ( StringUtils.isEmpty( columnName ) )
@@ -114,7 +114,7 @@ public class CassandraUtils
             return null;
         }
 
-        HColumn<String, Long> hColumn = columnSlice.getColumnByName( columnName );
+        HColumn<String, T> hColumn = columnSlice.getColumnByName( columnName );
         return hColumn == null ? null : ss.fromByteBuffer( hColumn.getValueBytes() );
     }
 
index ae494e1ab6d76bcc6e791856403ff7a4cb2bff7b..a2347bf1b6125483ad92c3b908fa42e20d4b43d6 100644 (file)
@@ -19,6 +19,8 @@ package org.apache.archiva.metadata.repository.cassandra.model;
  * under the License.
  */
 
+import static org.apache.archiva.metadata.repository.cassandra.model.ColumnNames.*;
+
 import org.apache.archiva.metadata.repository.cassandra.CassandraUtils;
 
 /**
@@ -29,6 +31,9 @@ import org.apache.archiva.metadata.repository.cassandra.CassandraUtils;
  */
 public class MetadataFacetModel
 {
+    public static final String[] COLUMNS = new String[] { FACET_ID.toString(), KEY.toString(), VALUE.toString(),
+        REPOSITORY_NAME.toString(), NAMESPACE_ID.toString(), PROJECT_ID.toString(), PROJECT_VERSION.toString() };
+
     private String facetId;
 
     private String key;
index 97b3718f7ce3567b41f221d7156c6abbf35ba4a2..b4f0cdb82e495eb1de92adb8069524f80c84dc88 100644 (file)
@@ -25,7 +25,6 @@ import org.apache.archiva.metadata.repository.cassandra.model.ProjectVersionMeta
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import javax.inject.Inject;
@@ -69,103 +68,6 @@ public class CassandraMetadataRepositoryTest
         clearReposAndNamespace( cassandraArchivaManager );
     }
 
-    @Override
-    @Ignore
-    public void testGetArtifactsByProjectVersionMetadata()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testGetArtifactsByProjectVersionMetadataNoRepository()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testGetArtifactsByProjectVersionMetadataAllRepositories()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testGetArtifactsByMetadataAllRepositories()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testGetArtifactsByPropertySingleResult()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testSearchArtifactsByKey()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testSearchArtifactsByKeyExact()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testSearchArtifactsFullText()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testSearchArtifactsFullTextExact()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testSearchArtifactsByFacetKeyAllRepos()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testSearchArtifactsByFacetKey()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-    @Override
-    @Ignore
-    public void testSearchArtifactsFullTextByFacet()
-        throws Exception
-    {
-        // TODO not implemented
-    }
-
-
     /**
      * ensure all dependant tables are cleaned up (mailinglist, license, dependencies)
      *
index d4c79b6039896aaed679c1b4cd218d080ff0a236..8fecba8a55282dba9696a55505f5b55e528ac706 100644 (file)
@@ -1403,6 +1403,9 @@ public class JcrMetadataRepository
     }
 
 
+    /**
+     * Exact is ignored as we can't do exact search in any property, we need a key
+     */
     @Override
     public List<ArtifactMetadata> searchArtifacts( String text, String repositoryId, boolean exact )
         throws MetadataRepositoryException