This project has retired. For details please refer to its Attic page.
CassandraMetadataRepository xref
View Javadoc
1   package org.apache.archiva.metadata.repository.cassandra;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import com.google.common.base.Predicate;
23  import com.google.common.collect.Iterables;
24  
25  import me.prettyprint.cassandra.serializers.LongSerializer;
26  import me.prettyprint.cassandra.serializers.StringSerializer;
27  import me.prettyprint.cassandra.service.template.ColumnFamilyResult;
28  import me.prettyprint.cassandra.service.template.ColumnFamilyTemplate;
29  import me.prettyprint.cassandra.service.template.ColumnFamilyUpdater;
30  import me.prettyprint.cassandra.service.template.ThriftColumnFamilyTemplate;
31  import me.prettyprint.hector.api.Keyspace;
32  import me.prettyprint.hector.api.beans.ColumnSlice;
33  import me.prettyprint.hector.api.beans.OrderedRows;
34  import me.prettyprint.hector.api.beans.Row;
35  import me.prettyprint.hector.api.exceptions.HInvalidRequestException;
36  import me.prettyprint.hector.api.factory.HFactory;
37  import me.prettyprint.hector.api.mutation.MutationResult;
38  import me.prettyprint.hector.api.mutation.Mutator;
39  import me.prettyprint.hector.api.query.QueryResult;
40  import me.prettyprint.hector.api.query.RangeSlicesQuery;
41  
42  import org.apache.archiva.configuration.ArchivaConfiguration;
43  import org.apache.archiva.metadata.model.ArtifactMetadata;
44  import org.apache.archiva.metadata.model.CiManagement;
45  import org.apache.archiva.metadata.model.Dependency;
46  import org.apache.archiva.metadata.model.FacetedMetadata;
47  import org.apache.archiva.metadata.model.IssueManagement;
48  import org.apache.archiva.metadata.model.License;
49  import org.apache.archiva.metadata.model.MailingList;
50  import org.apache.archiva.metadata.model.MetadataFacet;
51  import org.apache.archiva.metadata.model.MetadataFacetFactory;
52  import org.apache.archiva.metadata.model.Organization;
53  import org.apache.archiva.metadata.model.ProjectMetadata;
54  import org.apache.archiva.metadata.model.ProjectVersionMetadata;
55  import org.apache.archiva.metadata.model.ProjectVersionReference;
56  import org.apache.archiva.metadata.model.Scm;
57  import org.apache.archiva.metadata.repository.MetadataRepository;
58  import org.apache.archiva.metadata.repository.MetadataRepositoryException;
59  import org.apache.archiva.metadata.repository.MetadataResolutionException;
60  import org.apache.archiva.metadata.repository.cassandra.model.ArtifactMetadataModel;
61  import org.apache.archiva.metadata.repository.cassandra.model.MetadataFacetModel;
62  import org.apache.archiva.metadata.repository.cassandra.model.Namespace;
63  import org.apache.archiva.metadata.repository.cassandra.model.Project;
64  import org.apache.archiva.metadata.repository.cassandra.model.ProjectVersionMetadataModel;
65  import org.apache.archiva.metadata.repository.cassandra.model.Repository;
66  import org.apache.commons.lang.StringUtils;
67  import org.modelmapper.ModelMapper;
68  import org.slf4j.Logger;
69  import org.slf4j.LoggerFactory;
70  
71  import javax.persistence.PersistenceException;
72  
73  import java.util.ArrayList;
74  import java.util.Collection;
75  import java.util.Collections;
76  import java.util.Date;
77  import java.util.HashMap;
78  import java.util.HashSet;
79  import java.util.Iterator;
80  import java.util.LinkedList;
81  import java.util.List;
82  import java.util.Map;
83  import java.util.Set;
84  import java.util.UUID;
85  
86  import static org.apache.archiva.metadata.repository.cassandra.CassandraUtils.*;
87  import static org.apache.archiva.metadata.repository.cassandra.model.ColumnNames.*;
88  
89  /**
90   * @author Olivier Lamy
91   * @since 2.0.0
92   */
93  public class CassandraMetadataRepository
94      implements MetadataRepository
95  {
96  
97      private Logger logger = LoggerFactory.getLogger( getClass() );
98  
99      private ArchivaConfiguration configuration;
100 
101     private final Map<String, MetadataFacetFactory> metadataFacetFactories;
102 
103     private final CassandraArchivaManager cassandraArchivaManager;
104 
105     private final ColumnFamilyTemplate<String, String> projectVersionMetadataTemplate;
106 
107     private final ColumnFamilyTemplate<String, String> projectTemplate;
108 
109     private final ColumnFamilyTemplate<String, String> artifactMetadataTemplate;
110 
111     private final ColumnFamilyTemplate<String, String> metadataFacetTemplate;
112 
113     private final ColumnFamilyTemplate<String, String> mailingListTemplate;
114 
115     private final ColumnFamilyTemplate<String, String> licenseTemplate;
116 
117     private final ColumnFamilyTemplate<String, String> dependencyTemplate;
118 
119     private final Keyspace keyspace;
120 
121     private final StringSerializer ss = StringSerializer.get();
122 
123     public CassandraMetadataRepository( Map<String, MetadataFacetFactory> metadataFacetFactories,
124                                         ArchivaConfiguration configuration,
125                                         CassandraArchivaManager cassandraArchivaManager )
126     {
127         this.metadataFacetFactories = metadataFacetFactories;
128         this.configuration = configuration;
129         this.cassandraArchivaManager = cassandraArchivaManager;
130         this.keyspace = cassandraArchivaManager.getKeyspace();
131 
132         this.projectVersionMetadataTemplate =
133             new ThriftColumnFamilyTemplate<>( cassandraArchivaManager.getKeyspace(), //
134                                               cassandraArchivaManager.getProjectVersionMetadataFamilyName(), //
135                                               StringSerializer.get(), //
136                                               StringSerializer.get() );
137 
138         this.projectTemplate = new ThriftColumnFamilyTemplate<>( cassandraArchivaManager.getKeyspace(), //
139                                                                  cassandraArchivaManager.getProjectFamilyName(), //
140                                                                  //
141                                                                  StringSerializer.get(), //
142                                                                  StringSerializer.get() );
143 
144         this.artifactMetadataTemplate = new ThriftColumnFamilyTemplate<>( cassandraArchivaManager.getKeyspace(), //
145                                                                           cassandraArchivaManager.getArtifactMetadataFamilyName(),
146                                                                           StringSerializer.get(), //
147                                                                           StringSerializer.get() );
148 
149         this.metadataFacetTemplate = new ThriftColumnFamilyTemplate<>( cassandraArchivaManager.getKeyspace(), //
150                                                                        cassandraArchivaManager.getMetadataFacetFamilyName(),
151                                                                        //
152                                                                        StringSerializer.get(), //
153                                                                        StringSerializer.get() );
154 
155         this.mailingListTemplate = new ThriftColumnFamilyTemplate<>( cassandraArchivaManager.getKeyspace(), //
156                                                                      cassandraArchivaManager.getMailingListFamilyName(),
157                                                                      //
158                                                                      StringSerializer.get(), //
159                                                                      StringSerializer.get() );
160 
161         this.licenseTemplate = new ThriftColumnFamilyTemplate<>( cassandraArchivaManager.getKeyspace(), //
162                                                                  cassandraArchivaManager.getLicenseFamilyName(),
163                                                                  //
164                                                                  StringSerializer.get(), //
165                                                                  StringSerializer.get() );
166 
167         this.dependencyTemplate = new ThriftColumnFamilyTemplate<>( cassandraArchivaManager.getKeyspace(), //
168                                                                     cassandraArchivaManager.getDependencyFamilyName(),
169                                                                     //
170                                                                     StringSerializer.get(), //
171                                                                     StringSerializer.get() );
172     }
173 
174 
175     /**
176      * if the repository doesn't exist it will be created
177      *
178      * @param repositoryId
179      * @return
180      */
181     public Repository getOrCreateRepository( String repositoryId )
182         throws MetadataRepositoryException
183     {
184         String cf = cassandraArchivaManager.getRepositoryFamilyName();
185 
186         QueryResult<OrderedRows<String, String, String>> result = HFactory //
187             .createRangeSlicesQuery( keyspace, StringSerializer.get(), StringSerializer.get(),
188                                      StringSerializer.get() ) //
189             .setColumnFamily( cf ) //
190             .setColumnNames( REPOSITORY_NAME.toString() ) //
191             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
192             .execute();
193 
194         if ( result.get().getCount() < 1 )
195         {
196             // we need to create the repository
197             Repository repository = new Repository( repositoryId );
198 
199             try
200             {
201                 MutationResult mutationResult = HFactory.createMutator( keyspace, StringSerializer.get() ) //
202                     .addInsertion( repositoryId, cf,
203                                    CassandraUtils.column( REPOSITORY_NAME.toString(), repository.getName() ) ) //
204                     .execute();
205                 logger.debug( "time to insert repository: {}", mutationResult.getExecutionTimeMicro() );
206                 return repository;
207             }
208             catch ( HInvalidRequestException e )
209             {
210                 logger.error( e.getMessage(), e );
211                 throw new MetadataRepositoryException( e.getMessage(), e );
212             }
213 
214         }
215 
216         return new Repository(
217             result.get().getList().get( 0 ).getColumnSlice().getColumnByName( REPOSITORY_NAME.toString() ).getValue() );
218     }
219 
220 
221     protected Repository getRepository( String repositoryId )
222         throws MetadataRepositoryException
223     {
224 
225         QueryResult<OrderedRows<String, String, String>> result = HFactory //
226             .createRangeSlicesQuery( keyspace, StringSerializer.get(), StringSerializer.get(),
227                                      StringSerializer.get() ) //
228             .setColumnFamily( cassandraArchivaManager.getRepositoryFamilyName() ) //
229             .setColumnNames( REPOSITORY_NAME.toString() ) //
230             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
231             .execute();
232         return ( result.get().getCount() > 0 ) ? new Repository( repositoryId ) : null;
233     }
234 
235     @Override
236     public void updateNamespace( String repositoryId, String namespaceId )
237         throws MetadataRepositoryException
238     {
239         updateOrAddNamespace( repositoryId, namespaceId );
240     }
241 
242     private Namespace updateOrAddNamespace( String repositoryId, String namespaceId )
243         throws MetadataRepositoryException
244     {
245         try
246         {
247             Repository repository = getOrCreateRepository( repositoryId );
248 
249             String key =
250                 new Namespace.KeyBuilder().withNamespace( namespaceId ).withRepositoryId( repositoryId ).build();
251 
252             Namespace namespace = getNamespace( repositoryId, namespaceId );
253             if ( namespace == null )
254             {
255                 String cf = cassandraArchivaManager.getNamespaceFamilyName();
256                 namespace = new Namespace( namespaceId, repository );
257                 HFactory.createMutator( keyspace, StringSerializer.get() )
258                     //  values
259                     .addInsertion( key, cf, CassandraUtils.column( NAME.toString(), namespace.getName() ) ) //
260                     .addInsertion( key, cf, CassandraUtils.column( REPOSITORY_NAME.toString(), repository.getName() ) ) //
261                     .execute();
262             }
263 
264             return namespace;
265         }
266         catch ( HInvalidRequestException e )
267         {
268             logger.error( e.getMessage(), e );
269             throw new MetadataRepositoryException( e.getMessage(), e );
270         }
271     }
272 
273     protected Namespace getNamespace( String repositoryId, String namespaceId )
274     {
275 
276         QueryResult<OrderedRows<String, String, String>> result = HFactory //
277             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
278             .setColumnFamily( cassandraArchivaManager.getNamespaceFamilyName() ) //
279             .setColumnNames( REPOSITORY_NAME.toString(), NAME.toString() ) //
280             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
281             .addEqualsExpression( NAME.toString(), namespaceId ) //
282             .execute();
283         if ( result.get().getCount() > 0 )
284         {
285             ColumnSlice<String, String> columnSlice = result.get().getList().get( 0 ).getColumnSlice();
286             return new Namespace( getStringValue( columnSlice, NAME.toString() ), //
287                                   new Repository( getStringValue( columnSlice, REPOSITORY_NAME.toString() ) ) );
288 
289         }
290         return null;
291     }
292 
293 
294     @Override
295     public void removeNamespace( String repositoryId, String namespaceId )
296         throws MetadataRepositoryException
297     {
298 
299         try
300         {
301             String key = new Namespace.KeyBuilder() //
302                 .withNamespace( namespaceId ) //
303                 .withRepositoryId( repositoryId ) //
304                 .build();
305 
306             HFactory.createMutator( cassandraArchivaManager.getKeyspace(), new StringSerializer() ) //
307                 .addDeletion( key, cassandraArchivaManager.getNamespaceFamilyName() ) //
308                 .execute();
309 
310             QueryResult<OrderedRows<String, String, String>> result = HFactory //
311                 .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
312                 .setColumnFamily( cassandraArchivaManager.getProjectFamilyName() ) //
313                 .setColumnNames( REPOSITORY_NAME.toString() ) //
314                 .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
315                 .addEqualsExpression( NAMESPACE_ID.toString(), namespaceId ) //
316                 .execute();
317 
318             for ( Row<String, String, String> row : result.get() )
319             {
320                 this.projectTemplate.deleteRow( row.getKey() );
321             }
322 
323             result = HFactory //
324                 .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
325                 .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
326                 .setColumnNames( REPOSITORY_NAME.toString() ) //
327                 .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
328                 .addEqualsExpression( NAMESPACE_ID.toString(), namespaceId ) //
329                 .execute();
330 
331             for ( Row<String, String, String> row : result.get() )
332             {
333                 this.projectVersionMetadataTemplate.deleteRow( row.getKey() );
334                 removeMailingList( row.getKey() );
335             }
336 
337             result = HFactory //
338                 .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
339                 .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
340                 .setColumnNames( REPOSITORY_NAME.toString() ) //
341                 .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
342                 .addEqualsExpression( NAMESPACE_ID.toString(), namespaceId ) //
343                 .execute();
344 
345             for ( Row<String, String, String> row : result.get() )
346             {
347                 this.artifactMetadataTemplate.deleteRow( row.getKey() );
348             }
349 
350             result = HFactory //
351                 .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
352                 .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
353                 .setColumnNames( REPOSITORY_NAME.toString() ) //
354                 .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
355                 .addEqualsExpression( NAMESPACE_ID.toString(), namespaceId ) //
356                 .execute();
357 
358             for ( Row<String, String, String> row : result.get() )
359             {
360                 this.metadataFacetTemplate.deleteRow( row.getKey() );
361             }
362 
363         }
364         catch ( HInvalidRequestException e )
365         {
366             logger.error( e.getMessage(), e );
367             throw new MetadataRepositoryException( e.getMessage(), e );
368         }
369     }
370 
371 
372     @Override
373     public void removeRepository( final String repositoryId )
374         throws MetadataRepositoryException
375     {
376 
377         // TODO use cql queries to delete all
378         List<String> namespacesKey = new ArrayList<>();
379 
380         QueryResult<OrderedRows<String, String, String>> result = HFactory //
381             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
382             .setColumnFamily( cassandraArchivaManager.getNamespaceFamilyName() ) //
383             .setColumnNames( REPOSITORY_NAME.toString() ) //
384             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
385             .execute();
386 
387         for ( Row<String, String, String> row : result.get().getList() )
388         {
389             namespacesKey.add( row.getKey() );
390         }
391 
392         HFactory.createMutator( cassandraArchivaManager.getKeyspace(), ss ) //
393             .addDeletion( namespacesKey, cassandraArchivaManager.getNamespaceFamilyName() ) //
394             .execute();
395 
396         //delete repositoryId
397         HFactory.createMutator( cassandraArchivaManager.getKeyspace(), ss ) //
398             .addDeletion( repositoryId, cassandraArchivaManager.getRepositoryFamilyName() ) //
399             .execute();
400 
401         result = HFactory //
402             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
403             .setColumnFamily( cassandraArchivaManager.getProjectFamilyName() ) //
404             .setColumnNames( REPOSITORY_NAME.toString() ) //
405             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
406             .execute();
407 
408         for ( Row<String, String, String> row : result.get() )
409         {
410             this.projectTemplate.deleteRow( row.getKey() );
411         }
412 
413         result = HFactory //
414             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
415             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
416             .setColumnNames( REPOSITORY_NAME.toString() ) //
417             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
418             .execute();
419 
420         for ( Row<String, String, String> row : result.get() )
421         {
422             this.projectVersionMetadataTemplate.deleteRow( row.getKey() );
423             removeMailingList( row.getKey() );
424         }
425 
426         result = HFactory //
427             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
428             .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
429             .setColumnNames( REPOSITORY_NAME.toString() ) //
430             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
431             .execute();
432 
433         for ( Row<String, String, String> row : result.get() )
434         {
435             this.artifactMetadataTemplate.deleteRow( row.getKey() );
436         }
437 
438         result = HFactory //
439             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
440             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
441             .setColumnNames( REPOSITORY_NAME.toString() ) //
442             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
443             .execute();
444 
445         for ( Row<String, String, String> row : result.get() )
446         {
447             this.metadataFacetTemplate.deleteRow( row.getKey() );
448         }
449 
450 
451     }
452 
453     @Override
454     public Collection<String> getRepositories()
455         throws MetadataRepositoryException
456     {
457         try
458         {
459             logger.debug( "getRepositories" );
460 
461             final QueryResult<OrderedRows<String, String, String>> cResult = //
462                 HFactory.createRangeSlicesQuery( cassandraArchivaManager.getKeyspace(), //
463                                                  ss, ss, ss ) //
464                     .setColumnFamily( cassandraArchivaManager.getRepositoryFamilyName() ) //
465                     .setColumnNames( REPOSITORY_NAME.toString() ) //
466                     .setRange( null, null, false, Integer.MAX_VALUE ) //
467                     .execute();
468 
469             List<String> repoIds = new ArrayList<>( cResult.get().getCount() );
470 
471             for ( Row<String, String, String> row : cResult.get() )
472             {
473                 repoIds.add( getStringValue( row.getColumnSlice(), REPOSITORY_NAME.toString() ) );
474             }
475 
476             return repoIds;
477         }
478         catch ( PersistenceException e )
479         {
480             throw new MetadataRepositoryException( e.getMessage(), e );
481         }
482 
483     }
484 
485     // FIXME this one need peformance improvement maybe a cache?
486     @Override
487     public Collection<String> getRootNamespaces( final String repoId )
488         throws MetadataResolutionException
489     {
490 
491         QueryResult<OrderedRows<String, String, String>> result = HFactory //
492             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
493             .setColumnFamily( cassandraArchivaManager.getNamespaceFamilyName() ) //
494             .setColumnNames( NAME.toString() ) //
495             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
496             .execute();
497 
498         Set<String> namespaces = new HashSet<String>( result.get().getCount() );
499 
500         for ( Row<String, String, String> row : result.get() )
501         {
502             namespaces.add( StringUtils.substringBefore( getStringValue( row.getColumnSlice(), NAME.toString() ), "." ) );
503         }
504 
505         return namespaces;
506     }
507 
508     // FIXME this one need peformance improvement maybe a cache?
509     @Override
510     public Collection<String> getNamespaces( final String repoId, final String namespaceId )
511         throws MetadataResolutionException
512     {
513 
514         QueryResult<OrderedRows<String, String, String>> result = HFactory //
515             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
516             .setColumnFamily( cassandraArchivaManager.getNamespaceFamilyName() ) //
517             .setColumnNames( NAME.toString() ) //
518             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
519             .execute();
520 
521         List<String> namespaces = new ArrayList<>( result.get().getCount() );
522 
523         for ( Row<String, String, String> row : result.get() )
524         {
525             String currentNamespace = getStringValue( row.getColumnSlice(), NAME.toString() );
526             if ( StringUtils.startsWith( currentNamespace, namespaceId ) //
527                 && ( StringUtils.length( currentNamespace ) > StringUtils.length( namespaceId ) ) )
528             {
529                 // store after namespaceId '.' but before next '.'
530                 // call org namespace org.apache.maven.shared -> stored apache
531 
532                 String calledNamespace = StringUtils.endsWith( namespaceId, "." ) ? namespaceId : namespaceId + ".";
533                 String storedNamespace = StringUtils.substringAfter( currentNamespace, calledNamespace );
534 
535                 storedNamespace = StringUtils.substringBefore( storedNamespace, "." );
536 
537                 namespaces.add( storedNamespace );
538             }
539         }
540 
541         return namespaces;
542 
543     }
544 
545     // only use for testing purpose
546     protected List<String> getNamespaces( final String repoId )
547         throws MetadataResolutionException
548     {
549 
550         QueryResult<OrderedRows<String, String, String>> result = HFactory //
551             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
552             .setColumnFamily( cassandraArchivaManager.getNamespaceFamilyName() ) //
553             .setColumnNames( NAME.toString() ) //
554             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
555             .execute();
556 
557         List<String> namespaces = new ArrayList<>( result.get().getCount() );
558 
559         for ( Row<String, String, String> row : result.get() )
560         {
561             namespaces.add( getStringValue( row.getColumnSlice(), NAME.toString() ) );
562         }
563 
564         return namespaces;
565     }
566 
567 
568     @Override
569     public void updateProject( String repositoryId, ProjectMetadata projectMetadata )
570         throws MetadataRepositoryException
571     {
572 
573         QueryResult<OrderedRows<String, String, String>> result = HFactory //
574             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
575             .setColumnFamily( cassandraArchivaManager.getProjectFamilyName() ) //
576             .setColumnNames( PROJECT_ID.toString() ) //
577             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
578             .addEqualsExpression( NAMESPACE_ID.toString(), projectMetadata.getNamespace() ) //
579             .addEqualsExpression( PROJECT_ID.toString(), projectMetadata.getId() ) //
580             .execute();
581 
582         // project exists ? if yes return nothing to update here
583         if ( result.get().getCount() > 0 )
584         {
585             return;
586         }
587         else
588         {
589             Namespace namespace = updateOrAddNamespace( repositoryId, projectMetadata.getNamespace() );
590 
591             String key =
592                 new Project.KeyBuilder().withProjectId( projectMetadata.getId() ).withNamespace( namespace ).build();
593 
594             String cf = cassandraArchivaManager.getProjectFamilyName();
595             projectTemplate.createMutator()
596                 //  values
597                 .addInsertion( key, cf, CassandraUtils.column( PROJECT_ID.toString(), projectMetadata.getId() ) ) //
598                 .addInsertion( key, cf, CassandraUtils.column( REPOSITORY_NAME.toString(), repositoryId ) ) //
599                 .addInsertion( key, cf, CassandraUtils.column( NAMESPACE_ID.toString(), projectMetadata.getNamespace() ) )//
600                 .execute();
601         }
602     }
603 
604     @Override
605     public Collection<String> getProjects( final String repoId, final String namespace )
606         throws MetadataResolutionException
607     {
608 
609         QueryResult<OrderedRows<String, String, String>> result = HFactory //
610             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
611             .setColumnFamily( cassandraArchivaManager.getProjectFamilyName() ) //
612             .setColumnNames( PROJECT_ID.toString() ) //
613             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
614             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
615             .execute();
616 
617         final Set<String> projects = new HashSet<String>( result.get().getCount() );
618 
619         for ( Row<String, String, String> row : result.get() )
620         {
621             projects.add( getStringValue( row.getColumnSlice(), PROJECT_ID.toString() ) );
622         }
623 
624         return projects;
625     }
626 
627     @Override
628     public void removeProject( final String repositoryId, final String namespaceId, final String projectId )
629         throws MetadataRepositoryException
630     {
631 
632         String key = new Project.KeyBuilder() //
633             .withProjectId( projectId ) //
634             .withNamespace( new Namespace( namespaceId, new Repository( repositoryId ) ) ) //
635             .build();
636 
637         this.projectTemplate.deleteRow( key );
638 
639         QueryResult<OrderedRows<String, String, String>> result = HFactory //
640             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
641             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
642             .setColumnNames( ID.toString() ) //
643             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
644             .addEqualsExpression( NAMESPACE_ID.toString(), namespaceId ) //
645             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
646             .execute();
647 
648         for ( Row<String, String, String> row : result.get() )
649         {
650             this.projectVersionMetadataTemplate.deleteRow( row.getKey() );
651             removeMailingList( row.getKey() );
652         }
653 
654         result = HFactory //
655             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
656             .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
657             .setColumnNames( PROJECT_ID.toString() ) //
658             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
659             .addEqualsExpression( NAMESPACE_ID.toString(), namespaceId ) //
660             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
661             .execute();
662 
663         for ( Row<String, String, String> row : result.get() )
664         {
665             this.artifactMetadataTemplate.deleteRow( row.getKey() );
666         }
667     }
668 
669     @Override
670     public Collection<String> getProjectVersions( final String repoId, final String namespace, final String projectId )
671         throws MetadataResolutionException
672     {
673 
674         QueryResult<OrderedRows<String, String, String>> result = HFactory //
675             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
676             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
677             .setColumnNames( PROJECT_VERSION.toString() ) //
678             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
679             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
680             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
681             .execute();
682 
683         int count = result.get().getCount();
684 
685         if ( count < 1 )
686         {
687             return Collections.emptyList();
688         }
689 
690         Set<String> versions = new HashSet<String>( count );
691 
692         for ( Row<String, String, String> orderedRows : result.get() )
693         {
694             versions.add( getStringValue( orderedRows.getColumnSlice(), PROJECT_VERSION.toString() ) );
695         }
696 
697         return versions;
698 
699     }
700 
701     @Override
702     public ProjectMetadata getProject( final String repoId, final String namespace, final String id )
703         throws MetadataResolutionException
704     {
705 
706         QueryResult<OrderedRows<String, String, String>> result = HFactory //
707             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
708             .setColumnFamily( cassandraArchivaManager.getProjectFamilyName() ) //
709             .setColumnNames( PROJECT_ID.toString() ) //
710             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
711             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
712             .addEqualsExpression( PROJECT_ID.toString(), id ) //
713             .execute();
714 
715         int count = result.get().getCount();
716 
717         if ( count < 1 )
718         {
719             return null;
720         }
721 
722         ProjectMetadata projectMetadata = new ProjectMetadata();
723         projectMetadata.setId( id );
724         projectMetadata.setNamespace( namespace );
725 
726         logger.debug( "getProject repoId: {}, namespace: {}, projectId: {} -> {}", repoId, namespace, id,
727                       projectMetadata );
728 
729         return projectMetadata;
730     }
731 
732     protected ProjectVersionMetadataModel mapProjectVersionMetadataModel( ColumnSlice<String, String> columnSlice )
733     {
734         ProjectVersionMetadataModel projectVersionMetadataModel = new ProjectVersionMetadataModel();
735         projectVersionMetadataModel.setId( getStringValue( columnSlice, ID.toString() ) );
736         projectVersionMetadataModel.setDescription( getStringValue( columnSlice, DESCRIPTION.toString() ) );
737         projectVersionMetadataModel.setName( getStringValue( columnSlice, NAME.toString() ) );
738         Namespace namespace = new Namespace( getStringValue( columnSlice, NAMESPACE_ID.toString() ), //
739                                              new Repository( getStringValue( columnSlice, REPOSITORY_NAME.toString() ) ) );
740         projectVersionMetadataModel.setNamespace( namespace );
741         projectVersionMetadataModel.setIncomplete(
742             Boolean.parseBoolean( getStringValue( columnSlice, "incomplete" ) ) );
743         projectVersionMetadataModel.setProjectId( getStringValue( columnSlice, PROJECT_ID.toString() ) );
744         projectVersionMetadataModel.setUrl( getStringValue( columnSlice, URL.toString() ) );
745         return projectVersionMetadataModel;
746     }
747 
748 
749     @Override
750     public void updateProjectVersion( String repositoryId, String namespaceId, String projectId,
751                                       ProjectVersionMetadata versionMetadata )
752         throws MetadataRepositoryException
753     {
754         try
755         {
756             Namespace namespace = getNamespace( repositoryId, namespaceId );
757 
758             if ( namespace == null )
759             {
760                 updateOrAddNamespace( repositoryId, namespaceId );
761             }
762 
763             if ( getProject( repositoryId, namespaceId, projectId ) == null )
764             {
765                 ProjectMetadata projectMetadata = new ProjectMetadata();
766                 projectMetadata.setNamespace( namespaceId );
767                 projectMetadata.setId( projectId );
768                 updateProject( repositoryId, projectMetadata );
769             }
770 
771         }
772         catch ( MetadataResolutionException e )
773         {
774             throw new MetadataRepositoryException( e.getMessage(), e );
775         }
776 
777         QueryResult<OrderedRows<String, String, String>> result = HFactory //
778             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
779             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
780             .setColumnNames( PROJECT_VERSION.toString() ) //
781             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
782             .addEqualsExpression( NAMESPACE_ID.toString(), namespaceId ) //
783             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
784             .addEqualsExpression( PROJECT_VERSION.toString(), versionMetadata.getId() ) //
785             .execute();
786 
787         ProjectVersionMetadataModel projectVersionMetadataModel = null;
788         boolean creation = true;
789         if ( result.get().getCount() > 0 )
790         {
791             projectVersionMetadataModel =
792                 mapProjectVersionMetadataModel( result.get().getList().get( 0 ).getColumnSlice() );
793             creation = false;
794         }
795         else
796         {
797             projectVersionMetadataModel = getModelMapper().map( versionMetadata, ProjectVersionMetadataModel.class );
798         }
799 
800         projectVersionMetadataModel.setProjectId( projectId );
801         projectVersionMetadataModel.setNamespace( new Namespace( namespaceId, new Repository( repositoryId ) ) );
802 
803         projectVersionMetadataModel.setCiManagement( versionMetadata.getCiManagement() );
804         projectVersionMetadataModel.setIssueManagement( versionMetadata.getIssueManagement() );
805         projectVersionMetadataModel.setOrganization( versionMetadata.getOrganization() );
806         projectVersionMetadataModel.setScm( versionMetadata.getScm() );
807 
808         projectVersionMetadataModel.setMailingLists( versionMetadata.getMailingLists() );
809         projectVersionMetadataModel.setDependencies( versionMetadata.getDependencies() );
810         projectVersionMetadataModel.setLicenses( versionMetadata.getLicenses() );
811 
812         // we don't test of repository and namespace really exist !
813         String key = new ProjectVersionMetadataModel.KeyBuilder() //
814             .withRepository( repositoryId ) //
815             .withNamespace( namespaceId ) //
816             .withProjectId( projectId ) //
817             .withProjectVersion( versionMetadata.getVersion() ) //
818             .withId( versionMetadata.getId() ) //
819             .build();
820 
821         // FIXME nested objects to store!!!
822         if ( creation )
823         {
824             String cf = cassandraArchivaManager.getProjectVersionMetadataFamilyName();
825             Mutator<String> mutator = projectVersionMetadataTemplate.createMutator()
826                 //  values
827                 .addInsertion( key, cf, column( PROJECT_ID.toString(), projectId ) ) //
828                 .addInsertion( key, cf, column( REPOSITORY_NAME.toString(), repositoryId ) ) //
829                 .addInsertion( key, cf, column( NAMESPACE_ID.toString(), namespaceId ) )//
830                 .addInsertion( key, cf, column( PROJECT_VERSION.toString(), versionMetadata.getVersion() ) ); //
831 
832             addInsertion( mutator, key, cf, DESCRIPTION.toString(), versionMetadata.getDescription() );
833 
834             addInsertion( mutator, key, cf, NAME.toString(), versionMetadata.getName() );
835 
836             addInsertion( mutator, key, cf, "incomplete", Boolean.toString( versionMetadata.isIncomplete() ) );
837 
838             addInsertion( mutator, key, cf, URL.toString(), versionMetadata.getUrl() );
839             {
840                 CiManagement ci = versionMetadata.getCiManagement();
841                 if ( ci != null )
842                 {
843                     addInsertion( mutator, key, cf, "ciManagement.system", ci.getSystem() );
844                     addInsertion( mutator, key, cf, "ciManagement.url", ci.getUrl() );
845                 }
846             }
847 
848             {
849                 IssueManagement issueManagement = versionMetadata.getIssueManagement();
850 
851                 if ( issueManagement != null )
852                 {
853                     addInsertion( mutator, key, cf, "issueManagement.system", issueManagement.getSystem() );
854                     addInsertion( mutator, key, cf, "issueManagement.url", issueManagement.getUrl() );
855                 }
856             }
857 
858             {
859                 Organization organization = versionMetadata.getOrganization();
860                 if ( organization != null )
861                 {
862                     addInsertion( mutator, key, cf, "organization.name", organization.getName() );
863                     addInsertion( mutator, key, cf, "organization.url", organization.getUrl() );
864                 }
865             }
866 
867             {
868                 Scm scm = versionMetadata.getScm();
869                 if ( scm != null )
870                 {
871                     addInsertion( mutator, key, cf, "scm.url", scm.getUrl() );
872                     addInsertion( mutator, key, cf, "scm.connection", scm.getConnection() );
873                     addInsertion( mutator, key, cf, "scm.developerConnection", scm.getDeveloperConnection() );
874                 }
875             }
876 
877             recordMailingList( key, versionMetadata.getMailingLists() );
878 
879             recordLicenses( key, versionMetadata.getLicenses() );
880 
881             recordDependencies( key, versionMetadata.getDependencies(), repositoryId );
882 
883             MutationResult mutationResult = mutator.execute();
884         }
885         else
886         {
887             ColumnFamilyUpdater<String, String> updater = projectVersionMetadataTemplate.createUpdater( key );
888             addUpdateStringValue( updater, PROJECT_ID.toString(), projectId );
889             addUpdateStringValue( updater, REPOSITORY_NAME.toString(), repositoryId );
890             addUpdateStringValue( updater, NAMESPACE_ID.toString(), namespaceId );
891             addUpdateStringValue( updater, PROJECT_VERSION.toString(), versionMetadata.getVersion() );
892             addUpdateStringValue( updater, DESCRIPTION.toString(), versionMetadata.getDescription() );
893 
894             addUpdateStringValue( updater, NAME.toString(), versionMetadata.getName() );
895 
896             updater.setString( "incomplete", Boolean.toString( versionMetadata.isIncomplete() ) );
897             addUpdateStringValue( updater, URL.toString(), versionMetadata.getUrl() );
898 
899             {
900                 CiManagement ci = versionMetadata.getCiManagement();
901                 if ( ci != null )
902                 {
903                     addUpdateStringValue( updater, "ciManagement.system", ci.getSystem() );
904                     addUpdateStringValue( updater, "ciManagement.url", ci.getUrl() );
905                 }
906             }
907             {
908                 IssueManagement issueManagement = versionMetadata.getIssueManagement();
909                 if ( issueManagement != null )
910                 {
911                     addUpdateStringValue( updater, "issueManagement.system", issueManagement.getSystem() );
912                     addUpdateStringValue( updater, "issueManagement.url", issueManagement.getUrl() );
913                 }
914             }
915             {
916                 Organization organization = versionMetadata.getOrganization();
917                 if ( organization != null )
918                 {
919                     addUpdateStringValue( updater, "organization.name", organization.getName() );
920                     addUpdateStringValue( updater, "organization.url", organization.getUrl() );
921                 }
922             }
923             {
924                 Scm scm = versionMetadata.getScm();
925                 if ( scm != null )
926                 {
927                     addUpdateStringValue( updater, "scm.url", scm.getUrl() );
928                     addUpdateStringValue( updater, "scm.connection", scm.getConnection() );
929                     addUpdateStringValue( updater, "scm.developerConnection", scm.getDeveloperConnection() );
930                 }
931             }
932 
933             // update is a delete record
934             removeMailingList( key );
935             recordMailingList( key, versionMetadata.getMailingLists() );
936 
937             removeLicenses( key );
938             recordLicenses( key, versionMetadata.getLicenses() );
939 
940             removeDependencies( key );
941             recordDependencies( key, versionMetadata.getDependencies(), repositoryId );
942 
943             projectVersionMetadataTemplate.update( updater );
944 
945         }
946 
947         ArtifactMetadataModel artifactMetadataModel = new ArtifactMetadataModel();
948         artifactMetadataModel.setRepositoryId( repositoryId );
949         artifactMetadataModel.setNamespace( namespaceId );
950         artifactMetadataModel.setProject( projectId );
951         artifactMetadataModel.setProjectVersion( versionMetadata.getVersion() );
952         artifactMetadataModel.setVersion( versionMetadata.getVersion() );
953         updateFacets( versionMetadata, artifactMetadataModel );
954 
955     }
956 
957 
958     @Override
959     public ProjectVersionMetadata getProjectVersion( final String repoId, final String namespace,
960                                                      final String projectId, final String projectVersion )
961         throws MetadataResolutionException
962     {
963 
964         QueryResult<OrderedRows<String, String, String>> result = HFactory //
965             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
966             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
967             .setColumnNames( PROJECT_VERSION.toString() ) //
968             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
969             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
970             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
971             .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion ) //
972             .execute();
973 
974         if ( result.get().getCount() < 1 )
975         {
976             return null;
977         }
978 
979         String key = result.get().iterator().next().getKey();
980 
981         ColumnFamilyResult<String, String> columnFamilyResult = this.projectVersionMetadataTemplate.queryColumns( key );
982 
983         if ( !columnFamilyResult.hasResults() )
984         {
985             return null;
986         }
987 
988         ProjectVersionMetadata projectVersionMetadata = new ProjectVersionMetadata();
989         projectVersionMetadata.setId( columnFamilyResult.getString( PROJECT_VERSION.toString() ) );
990         projectVersionMetadata.setDescription( columnFamilyResult.getString( DESCRIPTION.toString() ) );
991         projectVersionMetadata.setName( columnFamilyResult.getString( NAME.toString() ) );
992 
993         projectVersionMetadata.setIncomplete( Boolean.parseBoolean( columnFamilyResult.getString( "incomplete" ) ) );
994 
995         projectVersionMetadata.setUrl( columnFamilyResult.getString( URL.toString() ) );
996         {
997             String ciUrl = columnFamilyResult.getString( "ciManagement.url" );
998             String ciSystem = columnFamilyResult.getString( "ciManagement.system" );
999 
1000             if ( StringUtils.isNotEmpty( ciSystem ) || StringUtils.isNotEmpty( ciUrl ) )
1001             {
1002                 projectVersionMetadata.setCiManagement( new CiManagement( ciSystem, ciUrl ) );
1003             }
1004         }
1005         {
1006             String issueUrl = columnFamilyResult.getString( "issueManagement.url" );
1007             String issueSystem = columnFamilyResult.getString( "issueManagement.system" );
1008             if ( StringUtils.isNotEmpty( issueSystem ) || StringUtils.isNotEmpty( issueUrl ) )
1009             {
1010                 projectVersionMetadata.setIssueManagement( new IssueManagement( issueSystem, issueUrl ) );
1011             }
1012         }
1013         {
1014             String organizationUrl = columnFamilyResult.getString( "organization.url" );
1015             String organizationName = columnFamilyResult.getString( "organization.name" );
1016             if ( StringUtils.isNotEmpty( organizationUrl ) || StringUtils.isNotEmpty( organizationName ) )
1017             {
1018                 projectVersionMetadata.setOrganization( new Organization( organizationName, organizationUrl ) );
1019             }
1020         }
1021         {
1022             String devConn = columnFamilyResult.getString( "scm.developerConnection" );
1023             String conn = columnFamilyResult.getString( "scm.connection" );
1024             String url = columnFamilyResult.getString( "scm.url" );
1025             if ( StringUtils.isNotEmpty( devConn ) || StringUtils.isNotEmpty( conn ) || StringUtils.isNotEmpty( url ) )
1026             {
1027                 projectVersionMetadata.setScm( new Scm( conn, devConn, url ) );
1028             }
1029         }
1030         projectVersionMetadata.setMailingLists( getMailingLists( key ) );
1031         projectVersionMetadata.setLicenses( getLicenses( key ) );
1032         projectVersionMetadata.setDependencies( getDependencies( key ) );
1033         // facets
1034 
1035         result = HFactory //
1036             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1037             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
1038             .setColumnNames( FACET_ID.toString(), KEY.toString(), VALUE.toString(), NAME.toString() ) //
1039             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
1040             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
1041             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
1042             .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion ) //
1043             .execute();
1044 
1045         Map<String, Map<String, String>> metadataFacetsPerFacetIds = new HashMap<>();
1046 
1047         for ( Row<String, String, String> row : result.get() )
1048         {
1049             ColumnSlice<String, String> columnSlice = row.getColumnSlice();
1050             String facetId = getStringValue( columnSlice, FACET_ID.toString() );
1051             Map<String, String> metaValues = metadataFacetsPerFacetIds.get( facetId );
1052             if ( metaValues == null )
1053             {
1054                 metaValues = new HashMap<>();
1055                 metadataFacetsPerFacetIds.put( facetId, metaValues );
1056             }
1057             metaValues.put( getStringValue( columnSlice, KEY.toString() ), getStringValue( columnSlice, VALUE.toString() ) );
1058         }
1059 
1060         if ( !metadataFacetsPerFacetIds.isEmpty() )
1061         {
1062             for ( Map.Entry<String, Map<String, String>> entry : metadataFacetsPerFacetIds.entrySet() )
1063             {
1064                 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( entry.getKey() );
1065                 if ( metadataFacetFactory != null )
1066                 {
1067                     MetadataFacet metadataFacet = metadataFacetFactory.createMetadataFacet();
1068                     metadataFacet.fromProperties( entry.getValue() );
1069                     projectVersionMetadata.addFacet( metadataFacet );
1070                 }
1071             }
1072         }
1073 
1074         return projectVersionMetadata;
1075     }
1076 
1077     protected void recordMailingList( String projectVersionMetadataKey, List<MailingList> mailingLists )
1078     {
1079         if ( mailingLists == null || mailingLists.isEmpty() )
1080         {
1081             return;
1082         }
1083         Mutator<String> mailingMutator = this.mailingListTemplate.createMutator();
1084         for ( MailingList mailingList : mailingLists )
1085         {
1086             // we don't care about the key as the real used one with the projectVersionMetadata
1087             String keyMailingList = UUID.randomUUID().toString();
1088             String cfMailingList = cassandraArchivaManager.getMailingListFamilyName();
1089 
1090             addInsertion( mailingMutator, keyMailingList, cfMailingList, "projectVersionMetadataModel.key",
1091                           projectVersionMetadataKey );
1092             addInsertion( mailingMutator, keyMailingList, cfMailingList, NAME.toString(), mailingList.getName() );
1093             addInsertion( mailingMutator, keyMailingList, cfMailingList, "mainArchiveUrl",
1094                           mailingList.getMainArchiveUrl() );
1095             addInsertion( mailingMutator, keyMailingList, cfMailingList, "postAddress", mailingList.getPostAddress() );
1096             addInsertion( mailingMutator, keyMailingList, cfMailingList, "subscribeAddress",
1097                           mailingList.getSubscribeAddress() );
1098             addInsertion( mailingMutator, keyMailingList, cfMailingList, "unsubscribeAddress",
1099                           mailingList.getUnsubscribeAddress() );
1100             int idx = 0;
1101             for ( String otherArchive : mailingList.getOtherArchives() )
1102             {
1103                 addInsertion( mailingMutator, keyMailingList, cfMailingList, "otherArchive." + idx, otherArchive );
1104                 idx++;
1105             }
1106 
1107         }
1108         mailingMutator.execute();
1109     }
1110 
1111     protected void removeMailingList( String projectVersionMetadataKey )
1112     {
1113 
1114         QueryResult<OrderedRows<String, String, String>> result =
1115             HFactory.createRangeSlicesQuery( cassandraArchivaManager.getKeyspace(), ss, ss, ss ) //
1116                 .setColumnFamily( cassandraArchivaManager.getMailingListFamilyName() ) //
1117                 .setColumnNames( NAME.toString() ) //
1118                 .setRowCount( Integer.MAX_VALUE ) //
1119                 .addEqualsExpression( "projectVersionMetadataModel.key", projectVersionMetadataKey ) //
1120                 .execute();
1121 
1122         if ( result.get().getCount() < 1 )
1123         {
1124             return;
1125         }
1126 
1127         for ( Row<String, String, String> row : result.get() )
1128         {
1129             this.mailingListTemplate.deleteRow( row.getKey() );
1130         }
1131 
1132     }
1133 
1134     protected List<MailingList> getMailingLists( String projectVersionMetadataKey )
1135     {
1136         List<MailingList> mailingLists = new ArrayList<>();
1137 
1138         QueryResult<OrderedRows<String, String, String>> result =
1139             HFactory.createRangeSlicesQuery( cassandraArchivaManager.getKeyspace(), ss, ss, ss ) //
1140                 .setColumnFamily( cassandraArchivaManager.getMailingListFamilyName() ) //
1141                 .setColumnNames( NAME.toString() ) //
1142                 .setRowCount( Integer.MAX_VALUE ) //
1143                 .addEqualsExpression( "projectVersionMetadataModel.key", projectVersionMetadataKey ) //
1144                 .execute();
1145         for ( Row<String, String, String> row : result.get() )
1146         {
1147             ColumnFamilyResult<String, String> columnFamilyResult =
1148                 this.mailingListTemplate.queryColumns( row.getKey() );
1149 
1150             MailingList mailingList = new MailingList();
1151             mailingList.setName( columnFamilyResult.getString( NAME.toString() ) );
1152             mailingList.setMainArchiveUrl( columnFamilyResult.getString( "mainArchiveUrl" ) );
1153             mailingList.setPostAddress( columnFamilyResult.getString( "postAddress" ) );
1154             mailingList.setSubscribeAddress( columnFamilyResult.getString( "subscribeAddress" ) );
1155             mailingList.setUnsubscribeAddress( columnFamilyResult.getString( "unsubscribeAddress" ) );
1156 
1157             List<String> otherArchives = new ArrayList<>();
1158 
1159             for ( String columnName : columnFamilyResult.getColumnNames() )
1160             {
1161                 if ( StringUtils.startsWith( columnName, "otherArchive." ) )
1162                 {
1163                     otherArchives.add( columnFamilyResult.getString( columnName ) );
1164                 }
1165             }
1166 
1167             mailingList.setOtherArchives( otherArchives );
1168             mailingLists.add( mailingList );
1169         }
1170 
1171         return mailingLists;
1172     }
1173 
1174     protected void recordLicenses( String projectVersionMetadataKey, List<License> licenses )
1175     {
1176 
1177         if ( licenses == null || licenses.isEmpty() )
1178         {
1179             return;
1180         }
1181         Mutator<String> licenseMutator = this.licenseTemplate.createMutator();
1182 
1183         for ( License license : licenses )
1184         {
1185             // we don't care about the key as the real used one with the projectVersionMetadata
1186             String keyLicense = UUID.randomUUID().toString();
1187             String cfLicense = cassandraArchivaManager.getLicenseFamilyName();
1188 
1189             addInsertion( licenseMutator, keyLicense, cfLicense, "projectVersionMetadataModel.key",
1190                           projectVersionMetadataKey );
1191 
1192             addInsertion( licenseMutator, keyLicense, cfLicense, NAME.toString(), license.getName() );
1193 
1194             addInsertion( licenseMutator, keyLicense, cfLicense, URL.toString(), license.getUrl() );
1195 
1196         }
1197         licenseMutator.execute();
1198     }
1199 
1200     protected void removeLicenses( String projectVersionMetadataKey )
1201     {
1202 
1203         QueryResult<OrderedRows<String, String, String>> result =
1204             HFactory.createRangeSlicesQuery( cassandraArchivaManager.getKeyspace(), ss, ss, ss ) //
1205                 .setColumnFamily( cassandraArchivaManager.getLicenseFamilyName() ) //
1206                 .setColumnNames( NAME.toString() ) //
1207                 .setRowCount( Integer.MAX_VALUE ) //
1208                 .addEqualsExpression( "projectVersionMetadataModel.key", projectVersionMetadataKey ) //
1209                 .execute();
1210         for ( Row<String, String, String> row : result.get() )
1211         {
1212             this.licenseTemplate.deleteRow( row.getKey() );
1213         }
1214     }
1215 
1216     protected List<License> getLicenses( String projectVersionMetadataKey )
1217     {
1218         List<License> licenses = new ArrayList<>();
1219 
1220         QueryResult<OrderedRows<String, String, String>> result =
1221             HFactory.createRangeSlicesQuery( cassandraArchivaManager.getKeyspace(), ss, ss, ss ) //
1222                 .setColumnFamily( cassandraArchivaManager.getLicenseFamilyName() ) //
1223                 .setColumnNames( "projectVersionMetadataModel.key" ) //
1224                 .setRowCount( Integer.MAX_VALUE ) //
1225                 .addEqualsExpression( "projectVersionMetadataModel.key", projectVersionMetadataKey ) //
1226                 .execute();
1227 
1228         for ( Row<String, String, String> row : result.get() )
1229         {
1230             ColumnFamilyResult<String, String> columnFamilyResult = this.licenseTemplate.queryColumns( row.getKey() );
1231 
1232             licenses.add(
1233                 new License( columnFamilyResult.getString( NAME.toString() ), columnFamilyResult.getString( URL.toString() ) ) );
1234         }
1235 
1236         return licenses;
1237     }
1238 
1239 
1240     protected void recordDependencies( String projectVersionMetadataKey, List<Dependency> dependencies,
1241                                        String repositoryId )
1242     {
1243 
1244         if ( dependencies == null || dependencies.isEmpty() )
1245         {
1246             return;
1247         }
1248         Mutator<String> dependencyMutator = this.dependencyTemplate.createMutator();
1249 
1250         for ( Dependency dependency : dependencies )
1251         {
1252             // we don't care about the key as the real used one with the projectVersionMetadata
1253             String keyDependency = UUID.randomUUID().toString();
1254             String cfDependency = cassandraArchivaManager.getDependencyFamilyName();
1255 
1256             addInsertion( dependencyMutator, keyDependency, cfDependency, "projectVersionMetadataModel.key",
1257                           projectVersionMetadataKey );
1258 
1259             addInsertion( dependencyMutator, keyDependency, cfDependency, REPOSITORY_NAME.toString(), repositoryId );
1260 
1261             addInsertion( dependencyMutator, keyDependency, cfDependency, "classifier", dependency.getClassifier() );
1262 
1263             addInsertion( dependencyMutator, keyDependency, cfDependency, "optional",
1264                           Boolean.toString( dependency.isOptional() ) );
1265 
1266             addInsertion( dependencyMutator, keyDependency, cfDependency, "scope", dependency.getScope() );
1267 
1268             addInsertion( dependencyMutator, keyDependency, cfDependency, "systemPath", dependency.getSystemPath() );
1269 
1270             addInsertion( dependencyMutator, keyDependency, cfDependency, "type", dependency.getType() );
1271 
1272             addInsertion( dependencyMutator, keyDependency, cfDependency, ARTIFACT_ID.toString(), dependency.getArtifactId() );
1273 
1274             addInsertion( dependencyMutator, keyDependency, cfDependency, GROUP_ID.toString(), dependency.getGroupId() );
1275 
1276             addInsertion( dependencyMutator, keyDependency, cfDependency, VERSION.toString(), dependency.getVersion() );
1277 
1278         }
1279         dependencyMutator.execute();
1280     }
1281 
1282     protected void removeDependencies( String projectVersionMetadataKey )
1283     {
1284 
1285         QueryResult<OrderedRows<String, String, String>> result =
1286             HFactory.createRangeSlicesQuery( cassandraArchivaManager.getKeyspace(), ss, ss, ss ) //
1287                 .setColumnFamily( cassandraArchivaManager.getDependencyFamilyName() ) //
1288                 .setColumnNames( GROUP_ID.toString() ) //
1289                 .setRowCount( Integer.MAX_VALUE ) //
1290                 .addEqualsExpression( "projectVersionMetadataModel.key", projectVersionMetadataKey ) //
1291                 .execute();
1292         for ( Row<String, String, String> row : result.get() )
1293         {
1294             this.dependencyTemplate.deleteRow( row.getKey() );
1295         }
1296     }
1297 
1298     protected List<Dependency> getDependencies( String projectVersionMetadataKey )
1299     {
1300         List<Dependency> dependencies = new ArrayList<>();
1301 
1302         QueryResult<OrderedRows<String, String, String>> result =
1303             HFactory.createRangeSlicesQuery( cassandraArchivaManager.getKeyspace(), ss, ss, ss ) //
1304                 .setColumnFamily( cassandraArchivaManager.getDependencyFamilyName() ) //
1305                 .setColumnNames( "projectVersionMetadataModel.key" ) //
1306                 .setRowCount( Integer.MAX_VALUE ) //
1307                 .addEqualsExpression( "projectVersionMetadataModel.key", projectVersionMetadataKey ) //
1308                 .execute();
1309 
1310         for ( Row<String, String, String> row : result.get() )
1311         {
1312             ColumnFamilyResult<String, String> columnFamilyResult =
1313                 this.dependencyTemplate.queryColumns( row.getKey() );
1314 
1315             Dependency dependency = new Dependency();
1316             dependency.setClassifier( columnFamilyResult.getString( "classifier" ) );
1317 
1318             dependency.setOptional( Boolean.parseBoolean( columnFamilyResult.getString( "optional" ) ) );
1319 
1320             dependency.setScope( columnFamilyResult.getString( "scope" ) );
1321 
1322             dependency.setSystemPath( columnFamilyResult.getString( "systemPath" ) );
1323 
1324             dependency.setType( columnFamilyResult.getString( "type" ) );
1325 
1326             dependency.setArtifactId( columnFamilyResult.getString( ARTIFACT_ID.toString() ) );
1327 
1328             dependency.setGroupId( columnFamilyResult.getString( GROUP_ID.toString() ) );
1329 
1330             dependency.setVersion( columnFamilyResult.getString( VERSION.toString() ) );
1331 
1332             dependencies.add( dependency );
1333         }
1334 
1335         return dependencies;
1336     }
1337 
1338     @Override
1339     public void updateArtifact( String repositoryId, String namespaceId, String projectId, String projectVersion,
1340                                 ArtifactMetadata artifactMeta )
1341         throws MetadataRepositoryException
1342     {
1343 
1344         Namespace namespace = getNamespace( repositoryId, namespaceId );
1345         if ( namespace == null )
1346         {
1347             namespace = updateOrAddNamespace( repositoryId, namespaceId );
1348         }
1349 
1350         ProjectMetadata projectMetadata = new ProjectMetadata();
1351         projectMetadata.setId( projectId );
1352         projectMetadata.setNamespace( namespaceId );
1353         updateProject( repositoryId, projectMetadata );
1354 
1355         String key = new ArtifactMetadataModel.KeyBuilder().withNamespace( namespace ).withProject( projectId ).withId(
1356             artifactMeta.getId() ).withProjectVersion( projectVersion ).build();
1357 
1358         // exists?
1359 
1360         boolean exists = this.artifactMetadataTemplate.isColumnsExist( key );
1361 
1362         if ( exists )
1363         {
1364             // updater
1365             ColumnFamilyUpdater<String, String> updater = this.artifactMetadataTemplate.createUpdater( key );
1366             updater.setLong( FILE_LAST_MODIFIED.toString(), artifactMeta.getFileLastModified().getTime() );
1367             updater.setLong( WHEN_GATHERED.toString(), artifactMeta.getWhenGathered().getTime() );
1368             updater.setLong( SIZE.toString(), artifactMeta.getSize() );
1369             addUpdateStringValue( updater, MD5.toString(), artifactMeta.getMd5() );
1370             addUpdateStringValue( updater, SHA1.toString(), artifactMeta.getSha1() );
1371             addUpdateStringValue( updater, VERSION.toString(), artifactMeta.getVersion() );
1372             this.artifactMetadataTemplate.update( updater );
1373         }
1374         else
1375         {
1376             String cf = this.cassandraArchivaManager.getArtifactMetadataFamilyName();
1377             // create
1378             this.artifactMetadataTemplate.createMutator() //
1379                 .addInsertion( key, cf, column( ID.toString(), artifactMeta.getId() ) )//
1380                 .addInsertion( key, cf, column( REPOSITORY_NAME.toString(), repositoryId ) ) //
1381                 .addInsertion( key, cf, column( NAMESPACE_ID.toString(), namespaceId ) ) //
1382                 .addInsertion( key, cf, column( PROJECT.toString(), artifactMeta.getProject() ) ) //
1383                 .addInsertion( key, cf, column( PROJECT_VERSION.toString(), projectVersion ) ) //
1384                 .addInsertion( key, cf, column( VERSION.toString(), artifactMeta.getVersion() ) ) //
1385                 .addInsertion( key, cf, column( FILE_LAST_MODIFIED.toString(), artifactMeta.getFileLastModified().getTime() ) ) //
1386                 .addInsertion( key, cf, column( SIZE.toString(), artifactMeta.getSize() ) ) //
1387                 .addInsertion( key, cf, column( MD5.toString(), artifactMeta.getMd5() ) ) //
1388                 .addInsertion( key, cf, column( SHA1.toString(), artifactMeta.getSha1() ) ) //
1389                 .addInsertion( key, cf, column( WHEN_GATHERED.toString(), artifactMeta.getWhenGathered().getTime() ) )//
1390                 .execute();
1391         }
1392 
1393         key = new ProjectVersionMetadataModel.KeyBuilder() //
1394             .withRepository( repositoryId ) //
1395             .withNamespace( namespace ) //
1396             .withProjectId( projectId ) //
1397             .withProjectVersion( projectVersion ) //
1398             .withId( artifactMeta.getId() ) //
1399             .build();
1400 
1401         QueryResult<OrderedRows<String, String, String>> result = HFactory //
1402             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1403             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
1404             .setColumnNames( VERSION.toString() ) //
1405             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
1406             .addEqualsExpression( NAMESPACE_ID.toString(), namespaceId ) //
1407             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
1408             .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion ) //
1409             .addEqualsExpression( VERSION.toString(), artifactMeta.getVersion() ) //
1410             .execute();
1411 
1412         exists = result.get().getCount() > 0;
1413 
1414         if ( !exists )
1415         {
1416             String cf = this.cassandraArchivaManager.getProjectVersionMetadataFamilyName();
1417 
1418             projectVersionMetadataTemplate.createMutator() //
1419                 .addInsertion( key, cf, column( NAMESPACE_ID.toString(), namespace.getName() ) ) //
1420                 .addInsertion( key, cf, column( REPOSITORY_NAME.toString(), repositoryId ) ) //
1421                 .addInsertion( key, cf, column( PROJECT_VERSION.toString(), projectVersion ) ) //
1422                 .addInsertion( key, cf, column( PROJECT_ID.toString(), projectId ) ) //
1423                 .addInsertion( key, cf, column( VERSION.toString(), artifactMeta.getVersion() ) ) //
1424                 .execute();
1425 
1426         }
1427 
1428         ArtifactMetadataModel artifactMetadataModel = new ArtifactMetadataModel();
1429 
1430         artifactMetadataModel.setRepositoryId( repositoryId );
1431         artifactMetadataModel.setNamespace( namespaceId );
1432         artifactMetadataModel.setProject( projectId );
1433         artifactMetadataModel.setProjectVersion( projectVersion );
1434         artifactMetadataModel.setVersion( artifactMeta.getVersion() );
1435         artifactMetadataModel.setFileLastModified( artifactMeta.getFileLastModified() == null
1436                                                        ? new Date().getTime()
1437                                                        : artifactMeta.getFileLastModified().getTime() );
1438 
1439         // now facets
1440         updateFacets( artifactMeta, artifactMetadataModel );
1441 
1442     }
1443 
1444     @Override
1445     public Collection<String> getArtifactVersions( final String repoId, final String namespace, final String projectId,
1446                                                    final String projectVersion )
1447         throws MetadataResolutionException
1448     {
1449 
1450         QueryResult<OrderedRows<String, String, String>> result = HFactory //
1451             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1452             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
1453             .setColumnNames( VERSION.toString() ) //
1454             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
1455             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
1456             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
1457             .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion ) //
1458             .execute();
1459 
1460         final Set<String> versions = new HashSet<String>();
1461 
1462         for ( Row<String, String, String> row : result.get() )
1463         {
1464             versions.add( getStringValue( row.getColumnSlice(), VERSION.toString() ) );
1465         }
1466 
1467         return versions;
1468 
1469     }
1470 
1471     /**
1472      * iterate over available facets to remove/add from the artifactMetadata
1473      *
1474      * @param facetedMetadata
1475      * @param artifactMetadataModel only use for the key
1476      */
1477     private void updateFacets( final FacetedMetadata facetedMetadata,
1478                                final ArtifactMetadataModel artifactMetadataModel )
1479     {
1480 
1481         String cf = cassandraArchivaManager.getMetadataFacetFamilyName();
1482 
1483         for ( final String facetId : metadataFacetFactories.keySet() )
1484         {
1485             MetadataFacet metadataFacet = facetedMetadata.getFacet( facetId );
1486             if ( metadataFacet == null )
1487             {
1488                 continue;
1489             }
1490             // clean first
1491 
1492             QueryResult<OrderedRows<String, String, String>> result =
1493                 HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1494                     .setColumnFamily( cf ) //
1495                     .setColumnNames( REPOSITORY_NAME.toString() ) //
1496                     .addEqualsExpression( REPOSITORY_NAME.toString(), artifactMetadataModel.getRepositoryId() ) //
1497                     .addEqualsExpression( NAMESPACE_ID.toString(), artifactMetadataModel.getNamespace() ) //
1498                     .addEqualsExpression( PROJECT_ID.toString(), artifactMetadataModel.getProject() ) //
1499                     .addEqualsExpression( PROJECT_VERSION.toString(), artifactMetadataModel.getProjectVersion() ) //
1500                     .addEqualsExpression( FACET_ID.toString(), facetId ) //
1501                     .execute();
1502 
1503             for ( Row<String, String, String> row : result.get().getList() )
1504             {
1505                 this.metadataFacetTemplate.deleteRow( row.getKey() );
1506             }
1507 
1508             Map<String, String> properties = metadataFacet.toProperties();
1509 
1510             for ( Map.Entry<String, String> entry : properties.entrySet() )
1511             {
1512                 String key = new MetadataFacetModel.KeyBuilder().withKey( entry.getKey() ).withArtifactMetadataModel(
1513                     artifactMetadataModel ).withFacetId( facetId ).withName( metadataFacet.getName() ).build();
1514                 Mutator<String> mutator = metadataFacetTemplate.createMutator() //
1515                     .addInsertion( key, cf, column( REPOSITORY_NAME.toString(), artifactMetadataModel.getRepositoryId() ) ) //
1516                     .addInsertion( key, cf, column( NAMESPACE_ID.toString(), artifactMetadataModel.getNamespace() ) ) //
1517                     .addInsertion( key, cf, column( PROJECT_ID.toString(), artifactMetadataModel.getProject() ) ) //
1518                     .addInsertion( key, cf, column( PROJECT_VERSION.toString(), artifactMetadataModel.getProjectVersion() ) ) //
1519                     .addInsertion( key, cf, column( FACET_ID.toString(), facetId ) ) //
1520                     .addInsertion( key, cf, column( KEY.toString(), entry.getKey() ) ) //
1521                     .addInsertion( key, cf, column( VALUE.toString(), entry.getValue() ) );
1522 
1523                 if ( metadataFacet.getName() != null )
1524                 {
1525                     mutator.addInsertion( key, cf, column( NAME.toString(), metadataFacet.getName() ) );
1526                 }
1527 
1528                 mutator.execute();
1529             }
1530         }
1531     }
1532 
1533 
1534     @Override
1535     public List<String> getMetadataFacets( final String repositoryId, final String facetId )
1536         throws MetadataRepositoryException
1537     {
1538 
1539         QueryResult<OrderedRows<String, String, String>> result = HFactory //
1540             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1541             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
1542             .setColumnNames( NAME.toString() ) //
1543             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
1544             .addEqualsExpression( FACET_ID.toString(), facetId ) //
1545             .execute();
1546 
1547         final List<String> facets = new ArrayList<>();
1548 
1549         for ( Row<String, String, String> row : result.get() )
1550         {
1551             facets.add( getStringValue( row.getColumnSlice(), NAME.toString() ) );
1552         }
1553         return facets;
1554     }
1555 
1556     @Override
1557     public boolean hasMetadataFacet( String repositoryId, String facetId )
1558         throws MetadataRepositoryException
1559     {
1560         return !getMetadataFacets( repositoryId, facetId ).isEmpty();
1561     }
1562 
1563     @Override
1564     public MetadataFacet getMetadataFacet( final String repositoryId, final String facetId, final String name )
1565         throws MetadataRepositoryException
1566     {
1567 
1568         MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
1569         if ( metadataFacetFactory == null )
1570         {
1571             return null;
1572         }
1573 
1574         QueryResult<OrderedRows<String, String, String>> result = HFactory //
1575             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1576             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
1577             .setColumnNames( KEY.toString(), VALUE.toString() ) //
1578             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
1579             .addEqualsExpression( FACET_ID.toString(), facetId ) //
1580             .addEqualsExpression( NAME.toString(), name ) //
1581             .execute();
1582 
1583         MetadataFacet metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name );
1584         int size = result.get().getCount();
1585         if ( size < 1 )
1586         {
1587             return null;
1588         }
1589         Map<String, String> map = new HashMap<>( size );
1590         for ( Row<String, String, String> row : result.get() )
1591         {
1592             ColumnSlice<String, String> columnSlice = row.getColumnSlice();
1593             map.put( getStringValue( columnSlice, KEY.toString() ), getStringValue( columnSlice, VALUE.toString() ) );
1594         }
1595         metadataFacet.fromProperties( map );
1596         return metadataFacet;
1597     }
1598 
1599     @Override
1600     public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet )
1601         throws MetadataRepositoryException
1602     {
1603 
1604         if ( metadataFacet == null )
1605         {
1606             return;
1607         }
1608 
1609         if ( metadataFacet.toProperties().isEmpty() )
1610         {
1611             String key = new MetadataFacetModel.KeyBuilder().withRepositoryId( repositoryId ).withFacetId(
1612                 metadataFacet.getFacetId() ).withName( metadataFacet.getName() ).build();
1613 
1614             boolean exists = this.metadataFacetTemplate.isColumnsExist( key );
1615 
1616             if ( exists )
1617             {
1618                 ColumnFamilyUpdater<String, String> updater = this.metadataFacetTemplate.createUpdater( key );
1619                 addUpdateStringValue( updater, FACET_ID.toString(), metadataFacet.getFacetId() );
1620                 addUpdateStringValue( updater, NAME.toString(), metadataFacet.getName() );
1621                 this.metadataFacetTemplate.update( updater );
1622             }
1623             else
1624             {
1625                 String cf = this.cassandraArchivaManager.getMetadataFacetFamilyName();
1626                 this.metadataFacetTemplate.createMutator() //
1627                     .addInsertion( key, cf, column( REPOSITORY_NAME.toString(), repositoryId ) ) //
1628                     .addInsertion( key, cf, column( FACET_ID.toString(), metadataFacet.getFacetId() ) ) //
1629                     .addInsertion( key, cf, column( NAME.toString(), metadataFacet.getName() ) ) //
1630                     .execute();
1631             }
1632 
1633         }
1634         else
1635         {
1636             for ( Map.Entry<String, String> entry : metadataFacet.toProperties().entrySet() )
1637             {
1638                 String key = new MetadataFacetModel.KeyBuilder().withRepositoryId( repositoryId ).withFacetId(
1639                     metadataFacet.getFacetId() ).withName( metadataFacet.getName() ).withKey( entry.getKey() ).build();
1640 
1641                 boolean exists = this.metadataFacetTemplate.isColumnsExist( key );
1642                 if ( !exists )
1643                 {
1644                     String cf = this.cassandraArchivaManager.getMetadataFacetFamilyName();
1645                     this.metadataFacetTemplate.createMutator() //
1646                         .addInsertion( key, cf, column( REPOSITORY_NAME.toString(), repositoryId ) ) //
1647                         .addInsertion( key, cf, column( FACET_ID.toString(), metadataFacet.getFacetId() ) ) //
1648                         .addInsertion( key, cf, column( NAME.toString(), metadataFacet.getName() ) ) //
1649                         .addInsertion( key, cf, column( KEY.toString(), entry.getKey() ) ) //
1650                         .addInsertion( key, cf, column( VALUE.toString(), entry.getValue() ) ) //
1651                         .execute();
1652                 }
1653                 else
1654                 {
1655                     ColumnFamilyUpdater<String, String> updater = this.metadataFacetTemplate.createUpdater( key );
1656                     addUpdateStringValue( updater, VALUE.toString(), entry.getValue() );
1657                     this.metadataFacetTemplate.update( updater );
1658                 }
1659             }
1660         }
1661     }
1662 
1663     @Override
1664     public void removeMetadataFacets( final String repositoryId, final String facetId )
1665         throws MetadataRepositoryException
1666     {
1667 
1668         QueryResult<OrderedRows<String, String, String>> result = HFactory //
1669             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1670             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
1671             .setColumnNames( KEY.toString(), VALUE.toString() ) //
1672             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
1673             .addEqualsExpression( FACET_ID.toString(), facetId ) //
1674             .execute();
1675 
1676         for ( Row<String, String, String> row : result.get() )
1677         {
1678             this.metadataFacetTemplate.deleteRow( row.getKey() );
1679         }
1680 
1681     }
1682 
1683     @Override
1684     public void removeMetadataFacet( final String repositoryId, final String facetId, final String name )
1685         throws MetadataRepositoryException
1686     {
1687 
1688         QueryResult<OrderedRows<String, String, String>> result = HFactory //
1689             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1690             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
1691             .setColumnNames( KEY.toString(), VALUE.toString() ) //
1692             .addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
1693             .addEqualsExpression( FACET_ID.toString(), facetId ) //
1694             .addEqualsExpression( NAME.toString(), name ) //
1695             .execute();
1696 
1697         for ( Row<String, String, String> row : result.get() )
1698         {
1699             this.metadataFacetTemplate.deleteRow( row.getKey() );
1700         }
1701     }
1702 
1703     @Override
1704     public List<ArtifactMetadata> getArtifactsByDateRange( final String repositoryId, final Date startTime,
1705                                                            final Date endTime )
1706         throws MetadataRepositoryException
1707     {
1708 
1709         LongSerializer ls = LongSerializer.get();
1710         RangeSlicesQuery<String, String, Long> query = HFactory //
1711             .createRangeSlicesQuery( keyspace, ss, ss, ls ) //
1712             .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
1713             .setColumnNames( ArtifactMetadataModel.COLUMNS ); //
1714 
1715         if ( startTime != null )
1716         {
1717             query = query.addGteExpression( WHEN_GATHERED.toString(), startTime.getTime() );
1718         }
1719         if ( endTime != null )
1720         {
1721             query = query.addLteExpression( WHEN_GATHERED.toString(), endTime.getTime() );
1722         }
1723         QueryResult<OrderedRows<String, String, Long>> result = query.execute();
1724 
1725         List<ArtifactMetadata> artifactMetadatas = new ArrayList<>( result.get().getCount() );
1726 
1727         for ( Row<String, String, Long> row : result.get() )
1728         {
1729             ColumnSlice<String, Long> columnSlice = row.getColumnSlice();
1730             String repositoryName = getAsStringValue( columnSlice, REPOSITORY_NAME.toString() );
1731             if ( StringUtils.equals( repositoryName, repositoryId ) )
1732             {
1733 
1734                 artifactMetadatas.add( mapArtifactMetadataLongColumnSlice( columnSlice ) );
1735             }
1736         }
1737 
1738         return artifactMetadatas;
1739     }
1740 
1741 
1742     protected ArtifactMetadata mapArtifactMetadataLongColumnSlice( ColumnSlice<String, Long> columnSlice )
1743     {
1744         ArtifactMetadata artifactMetadata = new ArtifactMetadata();
1745         artifactMetadata.setNamespace( getAsStringValue( columnSlice, NAMESPACE_ID.toString() ) );
1746         artifactMetadata.setSize( getLongValue( columnSlice, SIZE.toString() ) );
1747         artifactMetadata.setId( getAsStringValue( columnSlice, ID.toString() ) );
1748         artifactMetadata.setFileLastModified( getLongValue( columnSlice, FILE_LAST_MODIFIED.toString() ) );
1749         artifactMetadata.setMd5( getAsStringValue( columnSlice, MD5.toString() ) );
1750         artifactMetadata.setProject( getAsStringValue( columnSlice, PROJECT.toString() ) );
1751         artifactMetadata.setProjectVersion( getAsStringValue( columnSlice, PROJECT_VERSION.toString() ) );
1752         artifactMetadata.setRepositoryId( getAsStringValue( columnSlice, REPOSITORY_NAME.toString() ) );
1753         artifactMetadata.setSha1( getAsStringValue( columnSlice, SHA1.toString() ) );
1754         artifactMetadata.setVersion( getAsStringValue( columnSlice, VERSION.toString() ) );
1755         Long whenGathered = getLongValue( columnSlice, WHEN_GATHERED.toString() );
1756         if ( whenGathered != null )
1757         {
1758             artifactMetadata.setWhenGathered( new Date( whenGathered ) );
1759         }
1760         return artifactMetadata;
1761     }
1762 
1763     protected ArtifactMetadata mapArtifactMetadataStringColumnSlice( ColumnSlice<String, String> columnSlice )
1764     {
1765         ArtifactMetadata artifactMetadata = new ArtifactMetadata();
1766         artifactMetadata.setNamespace( getStringValue( columnSlice, NAMESPACE_ID.toString() ) );
1767         artifactMetadata.setSize( getAsLongValue( columnSlice, SIZE.toString() ) );
1768         artifactMetadata.setId( getStringValue( columnSlice, ID.toString() ) );
1769         artifactMetadata.setFileLastModified( getAsLongValue( columnSlice, FILE_LAST_MODIFIED.toString() ) );
1770         artifactMetadata.setMd5( getStringValue( columnSlice, MD5.toString() ) );
1771         artifactMetadata.setProject( getStringValue( columnSlice, PROJECT.toString() ) );
1772         artifactMetadata.setProjectVersion( getStringValue( columnSlice, PROJECT_VERSION.toString() ) );
1773         artifactMetadata.setRepositoryId( getStringValue( columnSlice, REPOSITORY_NAME.toString() ) );
1774         artifactMetadata.setSha1( getStringValue( columnSlice, SHA1.toString() ) );
1775         artifactMetadata.setVersion( getStringValue( columnSlice, VERSION.toString() ) );
1776         Long whenGathered = getAsLongValue( columnSlice, WHEN_GATHERED.toString() );
1777         if ( whenGathered != null )
1778         {
1779             artifactMetadata.setWhenGathered( new Date( whenGathered ) );
1780         }
1781         return artifactMetadata;
1782     }
1783 
1784     @Override
1785     public Collection<ArtifactMetadata> getArtifactsByChecksum( final String repositoryId, final String checksum )
1786         throws MetadataRepositoryException
1787     {
1788 
1789         // cql cannot run or in queries so running twice the query
1790         Map<String, ArtifactMetadata> artifactMetadataMap = new HashMap<>();
1791 
1792         RangeSlicesQuery<String, String, String> query = HFactory //
1793             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1794             .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
1795             .setColumnNames( ArtifactMetadataModel.COLUMNS ); //
1796 
1797         query = query.addEqualsExpression( SHA1.toString(), checksum ).addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId );
1798 
1799         QueryResult<OrderedRows<String, String, String>> result = query.execute();
1800 
1801         for ( Row<String, String, String> row : result.get() )
1802         {
1803             ColumnSlice<String, String> columnSlice = row.getColumnSlice();
1804 
1805             artifactMetadataMap.put( row.getKey(), mapArtifactMetadataStringColumnSlice( columnSlice ) );
1806 
1807         }
1808 
1809         query = HFactory //
1810             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1811             .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
1812             .setColumnNames( NAMESPACE_ID.toString(), SIZE.toString(), ID.toString(), FILE_LAST_MODIFIED.toString(), MD5.toString(), PROJECT.toString(), PROJECT_VERSION.toString(),
1813                              REPOSITORY_NAME.toString(), VERSION.toString(), WHEN_GATHERED.toString(), SHA1.toString() ); //
1814 
1815         query = query.addEqualsExpression( MD5.toString(), checksum ).addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId );
1816 
1817         result = query.execute();
1818 
1819         for ( Row<String, String, String> row : result.get() )
1820         {
1821             ColumnSlice<String, String> columnSlice = row.getColumnSlice();
1822 
1823             artifactMetadataMap.put( row.getKey(), mapArtifactMetadataStringColumnSlice( columnSlice ) );
1824 
1825         }
1826 
1827         return artifactMetadataMap.values();
1828     }
1829 
1830     /**
1831      * Project version and artifact level metadata are stored in the same place, no distinctions in Cassandra
1832      * implementation, just calls {@link #getArtifactsByMetadata(String, String, String)}
1833      */
1834     @Override
1835     public List<ArtifactMetadata> getArtifactsByProjectVersionMetadata( String key, String value, String repositoryId )
1836         throws MetadataRepositoryException
1837     {
1838         return getArtifactsByMetadata( key, value, repositoryId );
1839     }
1840 
1841     @Override
1842     public List<ArtifactMetadata> getArtifactsByMetadata( String key, String value, String repositoryId )
1843         throws MetadataRepositoryException
1844     {
1845         RangeSlicesQuery<String, String, String> query =
1846             HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1847             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
1848             .setColumnNames( MetadataFacetModel.COLUMNS ) //
1849             .addEqualsExpression( VALUE.toString(), value );
1850 
1851         if ( key != null )
1852         {
1853             query.addEqualsExpression( KEY.toString(), key ); //
1854         }
1855         if ( repositoryId != null )
1856         {
1857             query.addEqualsExpression( "repositoryName", repositoryId );
1858         }
1859 
1860         QueryResult<OrderedRows<String, String, String>> metadataFacetResult = query.execute();
1861         if ( metadataFacetResult.get() == null || metadataFacetResult.get().getCount() < 1 )
1862         {
1863             return Collections.emptyList();
1864         }
1865 
1866         List<ArtifactMetadata> artifactMetadatas = new LinkedList<ArtifactMetadata>();
1867 
1868         // TODO doing multiple queries, there should be a way to get all the artifactMetadatas for any number of
1869         // projects
1870         for ( Row<String, String, String> row : metadataFacetResult.get() )
1871         {
1872             QueryResult<OrderedRows<String, String, String>> artifactMetadataResult =
1873                 HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1874                 .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
1875                 .setColumnNames( ArtifactMetadataModel.COLUMNS ) //
1876                 .setRowCount( Integer.MAX_VALUE ) //
1877                 .addEqualsExpression( REPOSITORY_NAME.toString(),
1878                                       getStringValue( row.getColumnSlice(), REPOSITORY_NAME ) ) //
1879                 .addEqualsExpression( NAMESPACE_ID.toString(), getStringValue( row.getColumnSlice(), NAMESPACE_ID ) ) //
1880                 .addEqualsExpression( PROJECT.toString(), getStringValue( row.getColumnSlice(), PROJECT_ID ) ) //
1881                 .addEqualsExpression( PROJECT_VERSION.toString(),
1882                                       getStringValue( row.getColumnSlice(), PROJECT_VERSION ) ) //
1883                 .execute();
1884 
1885             if ( artifactMetadataResult.get() == null || artifactMetadataResult.get().getCount() < 1 )
1886             {
1887                 return Collections.emptyList();
1888             }
1889 
1890             for ( Row<String, String, String> artifactMetadataRow : artifactMetadataResult.get() )
1891             {
1892                 artifactMetadatas.add( mapArtifactMetadataStringColumnSlice( artifactMetadataRow.getColumnSlice() ) );
1893             }
1894         }
1895 
1896         return mapArtifactMetadataToArtifact( metadataFacetResult, artifactMetadatas );
1897     }
1898 
1899     @Override
1900     public List<ArtifactMetadata> getArtifactsByProperty( String key, String value, String repositoryId )
1901         throws MetadataRepositoryException
1902     {
1903         QueryResult<OrderedRows<String, String, String>> result =
1904             HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1905             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
1906             .setColumnNames( PROJECT_ID.toString(), REPOSITORY_NAME.toString(), NAMESPACE_ID.toString(),
1907                              PROJECT_VERSION.toString() ) //
1908             .addEqualsExpression( key, value ) //
1909             .execute();
1910 
1911         int count = result.get().getCount();
1912 
1913         if ( count < 1 )
1914         {
1915             return Collections.emptyList();
1916         }
1917 
1918         List<ArtifactMetadata> artifacts = new LinkedList<ArtifactMetadata>();
1919 
1920         for ( Row<String, String, String> row : result.get() )
1921         {
1922             // TODO doing multiple queries, there should be a way to get all the artifactMetadatas for any number of
1923             // projects
1924             try
1925             {
1926                 artifacts.addAll( getArtifacts( getStringValue( row.getColumnSlice(), REPOSITORY_NAME ),
1927                                                 getStringValue( row.getColumnSlice(), NAMESPACE_ID ),
1928                                                 getStringValue( row.getColumnSlice(), PROJECT_ID ),
1929                                                 getStringValue( row.getColumnSlice(), PROJECT_VERSION ) ) );
1930             }
1931             catch ( MetadataResolutionException e )
1932             {
1933                 // never raised
1934                 throw new IllegalStateException( e );
1935             }
1936         }
1937         return artifacts;
1938     }
1939 
1940     @Override
1941     public void removeArtifact( final String repositoryId, final String namespace, final String project,
1942                                 final String version, final String id )
1943         throws MetadataRepositoryException
1944     {
1945         logger.debug( "removeArtifact repositoryId: '{}', namespace: '{}', project: '{}', version: '{}', id: '{}'",
1946                       repositoryId, namespace, project, version, id );
1947         String key =
1948             new ArtifactMetadataModel.KeyBuilder().withRepositoryId( repositoryId ).withNamespace( namespace ).withId(
1949                 id ).withProjectVersion( version ).withProject( project ).build();
1950 
1951         this.artifactMetadataTemplate.deleteRow( key );
1952 
1953         key = new ProjectVersionMetadataModel.KeyBuilder() //
1954             .withRepository( repositoryId ) //
1955             .withNamespace( namespace ) //
1956             .withProjectId( project ) //
1957             .withProjectVersion( version ) //
1958             .withId( id ) //
1959             .build();
1960 
1961         this.projectVersionMetadataTemplate.deleteRow( key );
1962     }
1963 
1964     @Override
1965     public void removeArtifact( ArtifactMetadata artifactMetadata, String baseVersion )
1966         throws MetadataRepositoryException
1967     {
1968         logger.debug( "removeArtifact repositoryId: '{}', namespace: '{}', project: '{}', version: '{}', id: '{}'",
1969                       artifactMetadata.getRepositoryId(), artifactMetadata.getNamespace(),
1970                       artifactMetadata.getProject(), baseVersion, artifactMetadata.getId() );
1971         String key =
1972             new ArtifactMetadataModel.KeyBuilder().withRepositoryId( artifactMetadata.getRepositoryId() ).withNamespace(
1973                 artifactMetadata.getNamespace() ).withId( artifactMetadata.getId() ).withProjectVersion(
1974                 baseVersion ).withProject( artifactMetadata.getProject() ).build();
1975 
1976         this.artifactMetadataTemplate.deleteRow( key );
1977 
1978     }
1979 
1980     @Override
1981     public void removeArtifact( final String repositoryId, final String namespace, final String project,
1982                                 final String version, final MetadataFacet metadataFacet )
1983         throws MetadataRepositoryException
1984     {
1985 
1986         RangeSlicesQuery<String, String, String> query = HFactory //
1987             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
1988             .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
1989             .setColumnNames( NAMESPACE_ID.toString() ); //
1990 
1991         query = query.addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId ) //
1992             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
1993             .addEqualsExpression( PROJECT.toString(), project ) //
1994             .addEqualsExpression( VERSION.toString(), version );
1995 
1996         QueryResult<OrderedRows<String, String, String>> result = query.execute();
1997 
1998         for ( Row<String, String, String> row : result.get() )
1999         {
2000             this.artifactMetadataTemplate.deleteRow( row.getKey() );
2001         }
2002     }
2003 
2004 
2005     @Override
2006     public List<ArtifactMetadata> getArtifacts( final String repositoryId )
2007         throws MetadataRepositoryException
2008     {
2009 
2010         RangeSlicesQuery<String, String, String> query = HFactory //
2011             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
2012             .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
2013             .setColumnNames( ArtifactMetadataModel.COLUMNS ); //
2014 
2015         query = query.addEqualsExpression( REPOSITORY_NAME.toString(), repositoryId );
2016 
2017         QueryResult<OrderedRows<String, String, String>> result = query.execute();
2018 
2019         List<ArtifactMetadata> artifactMetadatas = new ArrayList<>( result.get().getCount() );
2020 
2021         for ( Row<String, String, String> row : result.get() )
2022         {
2023             ColumnSlice<String, String> columnSlice = row.getColumnSlice();
2024 
2025             artifactMetadatas.add( mapArtifactMetadataStringColumnSlice( columnSlice ) );
2026 
2027         }
2028 
2029         return artifactMetadatas;
2030     }
2031 
2032 
2033     @Override
2034     public Collection<ProjectVersionReference> getProjectReferences( String repoId, String namespace, String projectId,
2035                                                                      String projectVersion )
2036         throws MetadataResolutionException
2037     {
2038         QueryResult<OrderedRows<String, String, String>> result = HFactory //
2039             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
2040             .setColumnFamily( cassandraArchivaManager.getDependencyFamilyName() ) //
2041             .setColumnNames( "projectVersionMetadataModel.key" ) //
2042             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
2043             .addEqualsExpression( GROUP_ID.toString(), namespace ) //
2044             .addEqualsExpression( ARTIFACT_ID.toString(), projectId ) //
2045             .addEqualsExpression( VERSION.toString(), projectVersion ) //
2046             .execute();
2047 
2048         List<String> dependenciesIds = new ArrayList<>( result.get().getCount() );
2049 
2050         for ( Row<String, String, String> row : result.get().getList() )
2051         {
2052             dependenciesIds.add( getStringValue( row.getColumnSlice(), "projectVersionMetadataModel.key" ) );
2053         }
2054 
2055         List<ProjectVersionReference> references = new ArrayList<>( result.get().getCount() );
2056 
2057         for ( String key : dependenciesIds )
2058         {
2059             ColumnFamilyResult<String, String> columnFamilyResult =
2060                 this.projectVersionMetadataTemplate.queryColumns( key );
2061             references.add( new ProjectVersionReference( ProjectVersionReference.ReferenceType.DEPENDENCY, //
2062                                                          columnFamilyResult.getString( PROJECT_ID.toString() ), //
2063                                                          columnFamilyResult.getString( NAMESPACE_ID.toString() ), //
2064                                                          columnFamilyResult.getString( PROJECT_VERSION.toString() ) ) );
2065         }
2066 
2067         return references;
2068     }
2069 
2070     @Override
2071     public void removeProjectVersion( final String repoId, final String namespace, final String projectId,
2072                                       final String projectVersion )
2073         throws MetadataRepositoryException
2074     {
2075 
2076         QueryResult<OrderedRows<String, String, String>> result = HFactory //
2077             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
2078             .setColumnFamily( cassandraArchivaManager.getProjectVersionMetadataFamilyName() ) //
2079             .setColumnNames( VERSION.toString() ) //
2080             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
2081             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
2082             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
2083             .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion ) //
2084             .execute();
2085 
2086         for ( Row<String, String, String> row : result.get().getList() )
2087         {
2088             this.projectVersionMetadataTemplate.deleteRow( row.getKey() );
2089             removeMailingList( row.getKey() );
2090             removeLicenses( row.getKey() );
2091             removeDependencies( row.getKey() );
2092         }
2093 
2094         RangeSlicesQuery<String, String, String> query = HFactory //
2095             .createRangeSlicesQuery( keyspace, ss, ss, ss ) //
2096             .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
2097             .setColumnNames( NAMESPACE_ID.toString() ); //
2098 
2099         query = query.addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
2100             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
2101             .addEqualsExpression( PROJECT.toString(), projectId ) //
2102             .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion );
2103 
2104         result = query.execute();
2105 
2106         for ( Row<String, String, String> row : result.get() )
2107         {
2108             this.artifactMetadataTemplate.deleteRow( row.getKey() );
2109 
2110         }
2111     }
2112 
2113     @Override
2114     public Collection<ArtifactMetadata> getArtifacts( final String repoId, final String namespace,
2115                                                       final String projectId, final String projectVersion )
2116         throws MetadataResolutionException
2117     {
2118 
2119         QueryResult<OrderedRows<String, String, String>> result =
2120             HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
2121                 .setColumnFamily( cassandraArchivaManager.getArtifactMetadataFamilyName() ) //
2122                 .setColumnNames( ArtifactMetadataModel.COLUMNS )//
2123                 .setRowCount( Integer.MAX_VALUE ) //
2124                 .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
2125                 .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
2126                 .addEqualsExpression( PROJECT.toString(), projectId ) //
2127                 .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion ) //
2128                 .execute();
2129 
2130         if ( result.get() == null || result.get().getCount() < 1 )
2131         {
2132             return Collections.emptyList();
2133         }
2134 
2135         List<ArtifactMetadata> artifactMetadatas = new ArrayList<>( result.get().getCount() );
2136 
2137         for ( Row<String, String, String> row : result.get() )
2138         {
2139             artifactMetadatas.add( mapArtifactMetadataStringColumnSlice( row.getColumnSlice() ) );
2140         }
2141 
2142         result = HFactory.createRangeSlicesQuery( keyspace, ss, ss, ss ) //
2143             .setColumnFamily( cassandraArchivaManager.getMetadataFacetFamilyName() ) //
2144             .setColumnNames( MetadataFacetModel.COLUMNS ) //
2145             .setRowCount( Integer.MAX_VALUE ) //
2146             .addEqualsExpression( REPOSITORY_NAME.toString(), repoId ) //
2147             .addEqualsExpression( NAMESPACE_ID.toString(), namespace ) //
2148             .addEqualsExpression( PROJECT_ID.toString(), projectId ) //
2149             .addEqualsExpression( PROJECT_VERSION.toString(), projectVersion ) //
2150             .execute();
2151 
2152         return mapArtifactMetadataToArtifact(result, artifactMetadatas);
2153     }
2154 
2155     /**
2156      * Attach metadata to each of the  ArtifactMetadata objects
2157      */
2158     private List<ArtifactMetadata> mapArtifactMetadataToArtifact(QueryResult<OrderedRows<String, String, String>> result, List<ArtifactMetadata> artifactMetadatas) {
2159         if ( result.get() == null || result.get().getCount() < 1 )
2160         {
2161             return artifactMetadatas;
2162         }
2163 
2164         final List<MetadataFacetModel> metadataFacetModels = new ArrayList<>( result.get().getCount() );
2165 
2166         for ( Row<String, String, String> row : result.get() )
2167         {
2168             ColumnSlice<String, String> columnSlice = row.getColumnSlice();
2169             MetadataFacetModel metadataFacetModel = new MetadataFacetModel();
2170             metadataFacetModel.setFacetId( getStringValue( columnSlice, FACET_ID.toString() ) );
2171             metadataFacetModel.setName( getStringValue( columnSlice, NAME.toString() ) );
2172             metadataFacetModel.setValue( getStringValue( columnSlice, VALUE.toString() ) );
2173             metadataFacetModel.setKey( getStringValue( columnSlice, KEY.toString() ) );
2174             metadataFacetModel.setProjectVersion( getStringValue( columnSlice, PROJECT_VERSION.toString() ) );
2175             metadataFacetModels.add( metadataFacetModel );
2176         }
2177 
2178         // rebuild MetadataFacet for artifacts
2179 
2180         for ( final ArtifactMetadata artifactMetadata : artifactMetadatas )
2181         {
2182             Iterable<MetadataFacetModel> metadataFacetModelIterable =
2183                 Iterables.filter( metadataFacetModels, new Predicate<MetadataFacetModel>()
2184                 {
2185                     @Override
2186                     public boolean apply( MetadataFacetModel metadataFacetModel )
2187                     {
2188                         if ( metadataFacetModel != null )
2189                         {
2190                             return StringUtils.equals( artifactMetadata.getVersion(),
2191                                                        metadataFacetModel.getProjectVersion() );
2192                         }
2193                         return false;
2194                     }
2195                 } );
2196             Iterator<MetadataFacetModel> iterator = metadataFacetModelIterable.iterator();
2197             Map<String, List<MetadataFacetModel>> metadataFacetValuesPerFacetId = new HashMap<>();
2198             while ( iterator.hasNext() )
2199             {
2200                 MetadataFacetModel metadataFacetModel = iterator.next();
2201                 List<MetadataFacetModel> values = metadataFacetValuesPerFacetId.get( metadataFacetModel.getName() );
2202                 if ( values == null )
2203                 {
2204                     values = new ArrayList<>();
2205                     metadataFacetValuesPerFacetId.put( metadataFacetModel.getFacetId(), values );
2206                 }
2207                 values.add( metadataFacetModel );
2208 
2209             }
2210 
2211             for ( Map.Entry<String, List<MetadataFacetModel>> entry : metadataFacetValuesPerFacetId.entrySet() )
2212             {
2213                 MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( entry.getKey() );
2214                 if ( metadataFacetFactory != null )
2215                 {
2216                     List<MetadataFacetModel> facetModels = entry.getValue();
2217                     if ( !facetModels.isEmpty() )
2218                     {
2219                         MetadataFacet metadataFacet = metadataFacetFactory.createMetadataFacet();
2220                         Map<String, String> props = new HashMap<>( facetModels.size() );
2221                         for ( MetadataFacetModel metadataFacetModel : facetModels )
2222                         {
2223                             props.put( metadataFacetModel.getKey(), metadataFacetModel.getValue() );
2224                         }
2225                         metadataFacet.fromProperties( props );
2226                         artifactMetadata.addFacet( metadataFacet );
2227                     }
2228                 }
2229             }
2230         }
2231 
2232         return artifactMetadatas;
2233     }
2234 
2235     @Override
2236     public void save()
2237     {
2238         logger.trace( "save" );
2239     }
2240 
2241     @Override
2242     public void close()
2243         throws MetadataRepositoryException
2244     {
2245         logger.trace( "close" );
2246     }
2247 
2248     @Override
2249     public void revert()
2250     {
2251         logger.warn( "CassandraMetadataRepository cannot revert" );
2252     }
2253 
2254     @Override
2255     public boolean canObtainAccess( Class<?> aClass )
2256     {
2257         return false;
2258     }
2259 
2260     @Override
2261     public <T> T obtainAccess( Class<T> aClass )
2262         throws MetadataRepositoryException
2263     {
2264         throw new IllegalArgumentException(
2265             "Access using " + aClass + " is not supported on the cassandra metadata storage" );
2266     }
2267 
2268 
2269     private static class ModelMapperHolder
2270     {
2271         private static ModelMapper MODEL_MAPPER = new ModelMapper();
2272     }
2273 
2274     protected ModelMapper getModelMapper()
2275     {
2276         return ModelMapperHolder.MODEL_MAPPER;
2277     }
2278 
2279     /**
2280      * This implementation just calls getArtifactsByMetadata( null, text, repositoryId ). We can't search artifacts by
2281      * any property.
2282      */
2283     @Override
2284     public List<ArtifactMetadata> searchArtifacts( String text, String repositoryId, boolean exact )
2285         throws MetadataRepositoryException
2286     {
2287         return getArtifactsByMetadata( null, text, repositoryId );
2288     }
2289 
2290     /**
2291      * The exact parameter is ignored as we can't do non exact searches in Cassandra
2292      */
2293     @Override
2294     public List<ArtifactMetadata> searchArtifacts( String key, String text, String repositoryId, boolean exact )
2295         throws MetadataRepositoryException
2296     {
2297         // TODO optimize
2298         List<ArtifactMetadata> artifacts = new LinkedList<ArtifactMetadata>();
2299         artifacts.addAll( getArtifactsByMetadata( key, text, repositoryId ) );
2300         artifacts.addAll( getArtifactsByProperty( key, text, repositoryId ) );
2301         return artifacts;
2302     }
2303 }