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