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