package org.apache.archiva.metadata.repository.file;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.archiva.metadata.model.ArtifactMetadata;
import org.apache.archiva.metadata.model.CiManagement;
import org.apache.archiva.metadata.model.Dependency;
import org.apache.archiva.metadata.model.IssueManagement;
import org.apache.archiva.metadata.model.License;
import org.apache.archiva.metadata.model.MailingList;
import org.apache.archiva.metadata.model.MetadataFacet;
import org.apache.archiva.metadata.model.MetadataFacetFactory;
import org.apache.archiva.metadata.model.Organization;
import org.apache.archiva.metadata.model.ProjectMetadata;
import org.apache.archiva.metadata.model.ProjectVersionMetadata;
import org.apache.archiva.metadata.model.ProjectVersionReference;
import org.apache.archiva.metadata.model.Scm;
import org.apache.archiva.metadata.repository.MetadataRepository;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * @plexus.component role="org.apache.archiva.metadata.repository.MetadataRepository"
 */
public class FileMetadataRepository
    implements MetadataRepository
{
    /**
     * @plexus.requirement role="org.apache.archiva.metadata.model.MetadataFacetFactory"
     */
    private Map<String, MetadataFacetFactory> metadataFacetFactories;

    /**
     * @plexus.requirement
     */
    private ArchivaConfiguration configuration;

    private static final Logger log = LoggerFactory.getLogger( FileMetadataRepository.class );

    private static final String PROJECT_METADATA_KEY = "project-metadata";

    private static final String PROJECT_VERSION_METADATA_KEY = "version-metadata";

    private static final String NAMESPACE_METADATA_KEY = "namespace-metadata";

    private static final String METADATA_KEY = "metadata";

    private File getBaseDirectory( String repoId )
    {
        // TODO: should be configurable, like the index
        String basedir = configuration.getConfiguration().getManagedRepositoriesAsMap().get( repoId ).getLocation();
        File dir = new File( basedir, ".archiva" );
        return dir;
    }

    private File getDirectory( String repoId )
    {
        return new File( getBaseDirectory( repoId ), "content" );
    }

    public void updateProject( String repoId, ProjectMetadata project )
    {
        updateProject( repoId, project.getNamespace(), project.getId() );
    }

    private void updateProject( String repoId, String namespace, String id )
    {
        // TODO: this is a more braindead implementation than we would normally expect, for prototyping purposes
        updateNamespace( repoId, namespace );

        try
        {
            File namespaceDirectory = new File( getDirectory( repoId ), namespace );
            Properties properties = new Properties();
            properties.setProperty( "namespace", namespace );
            properties.setProperty( "id", id );
            writeProperties( properties, new File( namespaceDirectory, id ), PROJECT_METADATA_KEY );
        }
        catch ( IOException e )
        {
            // TODO!
            e.printStackTrace();
        }
    }

    public void updateProjectVersion( String repoId, String namespace, String projectId,
                                      ProjectVersionMetadata versionMetadata )
    {
        updateProject( repoId, namespace, projectId );

        File directory = new File( getDirectory( repoId ),
                                   namespace + "/" + projectId + "/" + versionMetadata.getId() );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
        // remove properties that are not references or artifacts
        for ( Object key : new ArrayList( properties.keySet() ) )
        {
            String name = (String) key;
            if ( !name.contains( ":" ) && !name.equals( "facetIds" ) )
            {
                properties.remove( name );
            }
        }
        properties.setProperty( "id", versionMetadata.getId() );
        setProperty( properties, "name", versionMetadata.getName() );
        setProperty( properties, "description", versionMetadata.getDescription() );
        setProperty( properties, "url", versionMetadata.getUrl() );
        setProperty( properties, "incomplete", String.valueOf( versionMetadata.isIncomplete() ) );
        if ( versionMetadata.getScm() != null )
        {
            setProperty( properties, "scm.connection", versionMetadata.getScm().getConnection() );
            setProperty( properties, "scm.developerConnection", versionMetadata.getScm().getDeveloperConnection() );
            setProperty( properties, "scm.url", versionMetadata.getScm().getUrl() );
        }
        if ( versionMetadata.getCiManagement() != null )
        {
            setProperty( properties, "ci.system", versionMetadata.getCiManagement().getSystem() );
            setProperty( properties, "ci.url", versionMetadata.getCiManagement().getUrl() );
        }
        if ( versionMetadata.getIssueManagement() != null )
        {
            setProperty( properties, "issue.system", versionMetadata.getIssueManagement().getSystem() );
            setProperty( properties, "issue.url", versionMetadata.getIssueManagement().getUrl() );
        }
        if ( versionMetadata.getOrganization() != null )
        {
            setProperty( properties, "org.name", versionMetadata.getOrganization().getName() );
            setProperty( properties, "org.url", versionMetadata.getOrganization().getUrl() );
        }
        int i = 0;
        for ( License license : versionMetadata.getLicenses() )
        {
            setProperty( properties, "license." + i + ".name", license.getName() );
            setProperty( properties, "license." + i + ".url", license.getUrl() );
            i++;
        }
        i = 0;
        for ( MailingList mailingList : versionMetadata.getMailingLists() )
        {
            setProperty( properties, "mailingList." + i + ".archive", mailingList.getMainArchiveUrl() );
            setProperty( properties, "mailingList." + i + ".name", mailingList.getName() );
            setProperty( properties, "mailingList." + i + ".post", mailingList.getPostAddress() );
            setProperty( properties, "mailingList." + i + ".unsubscribe", mailingList.getUnsubscribeAddress() );
            setProperty( properties, "mailingList." + i + ".subscribe", mailingList.getSubscribeAddress() );
            setProperty( properties, "mailingList." + i + ".otherArchives", join( mailingList.getOtherArchives() ) );
            i++;
        }
        i = 0;
        for ( Dependency dependency : versionMetadata.getDependencies() )
        {
            setProperty( properties, "dependency." + i + ".classifier", dependency.getClassifier() );
            setProperty( properties, "dependency." + i + ".scope", dependency.getScope() );
            setProperty( properties, "dependency." + i + ".systemPath", dependency.getSystemPath() );
            setProperty( properties, "dependency." + i + ".artifactId", dependency.getArtifactId() );
            setProperty( properties, "dependency." + i + ".groupId", dependency.getGroupId() );
            setProperty( properties, "dependency." + i + ".version", dependency.getVersion() );
            setProperty( properties, "dependency." + i + ".type", dependency.getType() );
            i++;
        }
        Set<String> facetIds = new LinkedHashSet<String>( versionMetadata.getFacetIds() );
        facetIds.addAll( Arrays.asList( properties.getProperty( "facetIds", "" ).split( "," ) ) );
        properties.setProperty( "facetIds", join( facetIds ) );

        for ( MetadataFacet facet : versionMetadata.getFacetList() )
        {
            properties.putAll( facet.toProperties() );
        }

        try
        {
            writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
        }
        catch ( IOException e )
        {
            // TODO
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    public void updateProjectReference( String repoId, String namespace, String projectId, String projectVersion,
                                        ProjectVersionReference reference )
    {
        File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
        int i = Integer.valueOf( properties.getProperty( "ref:lastReferenceNum", "-1" ) ) + 1;
        setProperty( properties, "ref:lastReferenceNum", Integer.toString( i ) );
        setProperty( properties, "ref:reference." + i + ".namespace", reference.getNamespace() );
        setProperty( properties, "ref:reference." + i + ".projectId", reference.getProjectId() );
        setProperty( properties, "ref:reference." + i + ".projectVersion", reference.getProjectVersion() );
        setProperty( properties, "ref:reference." + i + ".referenceType", reference.getReferenceType().toString() );

        try
        {
            writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
        }
        catch ( IOException e )
        {
            // TODO
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    public void updateNamespace( String repoId, String namespace )
    {
        try
        {
            File namespaceDirectory = new File( getDirectory( repoId ), namespace );
            Properties properties = new Properties();
            properties.setProperty( "namespace", namespace );
            writeProperties( properties, namespaceDirectory, NAMESPACE_METADATA_KEY );

        }
        catch ( IOException e )
        {
            // TODO!
            e.printStackTrace();
        }
    }

    public List<String> getMetadataFacets( String repoId, String facetId )
    {
        File directory = getMetadataDirectory( repoId, facetId );
        List<String> facets = new ArrayList<String>();
        recurse( facets, "", directory );
        return facets;
    }

    private void recurse( List<String> facets, String prefix, File directory )
    {
        File[] list = directory.listFiles();
        if ( list != null )
        {
            for ( File dir : list )
            {
                if ( dir.isDirectory() )
                {
                    recurse( facets, prefix + "/" + dir.getName(), dir );
                }
                else if ( dir.getName().equals( METADATA_KEY + ".properties" ) )
                {
                    facets.add( prefix.substring( 1 ) );
                }
            }
        }
    }

    public MetadataFacet getMetadataFacet( String repositoryId, String facetId, String name )
    {
        Properties properties;
        try
        {
            properties = readProperties( new File( getMetadataDirectory( repositoryId, facetId ), name ),
                                         METADATA_KEY );
        }
        catch ( FileNotFoundException e )
        {
            return null;
        }
        catch ( IOException e )
        {
            // TODO
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            return null;
        }
        MetadataFacet metadataFacet = null;
        MetadataFacetFactory metadataFacetFactory = metadataFacetFactories.get( facetId );
        if ( metadataFacetFactory != null )
        {
            metadataFacet = metadataFacetFactory.createMetadataFacet( repositoryId, name );
            Map<String, String> map = new HashMap<String, String>();
            for ( Object key : new ArrayList( properties.keySet() ) )
            {
                String property = (String) key;
                map.put( property, properties.getProperty( property ) );
            }
            metadataFacet.fromProperties( map );
        }
        return metadataFacet;
    }

    public void addMetadataFacet( String repositoryId, MetadataFacet metadataFacet )
    {
        Properties properties = new Properties();
        properties.putAll( metadataFacet.toProperties() );

        try
        {
            File directory = new File( getMetadataDirectory( repositoryId, metadataFacet.getFacetId() ),
                                       metadataFacet.getName() );
            writeProperties( properties, directory, METADATA_KEY );
        }
        catch ( IOException e )
        {
            // TODO!
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    public void removeMetadataFacets( String repositoryId, String facetId )
    {
        try
        {
            FileUtils.deleteDirectory( getMetadataDirectory( repositoryId, facetId ) );
        }
        catch ( IOException e )
        {
            // TODO!
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    public void removeMetadataFacet( String repoId, String facetId, String name )
    {
        File dir = new File( getMetadataDirectory( repoId, facetId ), name );
        try
        {
            FileUtils.deleteDirectory( dir );
        }
        catch ( IOException e )
        {
            // TODO
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    public List<ArtifactMetadata> getArtifactsByDateRange( String repoId, Date startTime, Date endTime )
    {
        // TODO: this is quite slow - if we are to persist with this repository implementation we should build an index
        //  of this information (eg. in Lucene, as before)

        List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
        for ( String ns : getRootNamespaces( repoId ) )
        {
            getArtifactsByDateRange( artifacts, repoId, ns, startTime, endTime );
        }
        Collections.sort( artifacts, new ArtifactComparator() );
        return artifacts;
    }

    private void getArtifactsByDateRange( List<ArtifactMetadata> artifacts, String repoId, String ns, Date startTime,
                                          Date endTime )
    {
        for ( String namespace : getNamespaces( repoId, ns ) )
        {
            getArtifactsByDateRange( artifacts, repoId, ns + "." + namespace, startTime, endTime );
        }

        for ( String project : getProjects( repoId, ns ) )
        {
            for ( String version : getProjectVersions( repoId, ns, project ) )
            {
                for ( ArtifactMetadata artifact : getArtifacts( repoId, ns, project, version ) )
                {
                    if ( startTime == null || startTime.before( artifact.getWhenGathered() ) )
                    {
                        if ( endTime == null || endTime.after( artifact.getWhenGathered() ) )
                        {
                            artifacts.add( artifact );
                        }
                    }
                }
            }
        }
    }

    public Collection<ArtifactMetadata> getArtifacts( String repoId, String namespace, String projectId,
                                                      String projectVersion )
    {
        Map<String, ArtifactMetadata> artifacts = new HashMap<String, ArtifactMetadata>();

        File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );

        for ( Map.Entry entry : properties.entrySet() )
        {
            String name = (String) entry.getKey();
            StringTokenizer tok = new StringTokenizer( name, ":" );
            if ( tok.hasMoreTokens() && "artifact".equals( tok.nextToken() ) )
            {
                String field = tok.nextToken();
                String id = tok.nextToken();

                ArtifactMetadata artifact = artifacts.get( id );
                if ( artifact == null )
                {
                    artifact = new ArtifactMetadata();
                    artifact.setRepositoryId( repoId );
                    artifact.setNamespace( namespace );
                    artifact.setProject( projectId );
                    artifact.setVersion( projectVersion );
                    artifact.setId( id );
                    artifacts.put( id, artifact );
                }

                String value = (String) entry.getValue();
                if ( "updated".equals( field ) )
                {
                    artifact.setFileLastModified( Long.valueOf( value ) );
                }
                else if ( "size".equals( field ) )
                {
                    artifact.setSize( Long.valueOf( value ) );
                }
                else if ( "whenGathered".equals( field ) )
                {
                    artifact.setWhenGathered( new Date( Long.valueOf( value ) ) );
                }
                else if ( "version".equals( field ) )
                {
                    artifact.setVersion( value );
                }
                else if ( "md5".equals( field ) )
                {
                    artifact.setMd5( value );
                }
                else if ( "sha1".equals( field ) )
                {
                    artifact.setSha1( value );
                }
            }
        }
        return artifacts.values();
    }

    public Collection<String> getRepositories()
    {
        return configuration.getConfiguration().getManagedRepositoriesAsMap().keySet();
    }

    public List<ArtifactMetadata> getArtifactsByChecksum( String repositoryId, String checksum )
    {
        // TODO: this is quite slow - if we are to persist with this repository implementation we should build an index
        //  of this information (eg. in Lucene, as before)
        // alternatively, we could build a referential tree in the content repository, however it would need some levels
        // of depth to avoid being too broad to be useful (eg. /repository/checksums/a/ab/abcdef1234567)

        List<ArtifactMetadata> artifacts = new ArrayList<ArtifactMetadata>();
        for ( String ns : getRootNamespaces( repositoryId ) )
        {
            getArtifactsByChecksum( artifacts, repositoryId, ns, checksum );
        }
        return artifacts;
    }

    public void deleteArtifact( String repoId, String namespace, String project, String version, String id )
    {
        File directory = new File( getDirectory( repoId ), namespace + "/" + project + "/" + version );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );

        properties.remove( "artifact:updated:" + id );
        properties.remove( "artifact:whenGathered:" + id );
        properties.remove( "artifact:size:" + id );
        properties.remove( "artifact:md5:" + id );
        properties.remove( "artifact:sha1:" + id );
        properties.remove( "artifact:version:" + id );

        try
        {
            writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
        }
        catch ( IOException e )
        {
            // TODO
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    public void deleteRepository( String repoId )
    {
        try
        {
            FileUtils.deleteDirectory( getDirectory( repoId ) );
        }
        catch ( IOException e )
        {
            // TODO
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    private void getArtifactsByChecksum( List<ArtifactMetadata> artifacts, String repositoryId, String ns,
                                         String checksum )
    {
        for ( String namespace : getNamespaces( repositoryId, ns ) )
        {
            getArtifactsByChecksum( artifacts, repositoryId, ns + "." + namespace, checksum );
        }

        for ( String project : getProjects( repositoryId, ns ) )
        {
            for ( String version : getProjectVersions( repositoryId, ns, project ) )
            {
                for ( ArtifactMetadata artifact : getArtifacts( repositoryId, ns, project, version ) )
                {
                    if ( checksum.equals( artifact.getMd5() ) || checksum.equals( artifact.getSha1() ) )
                    {
                        artifacts.add( artifact );
                    }
                }
            }
        }
    }

    private File getMetadataDirectory( String repoId, String facetId )
    {
        return new File( getBaseDirectory( repoId ), "facets/" + facetId );
    }

    private String join( Collection<String> ids )
    {
        if ( !ids.isEmpty() )
        {
            StringBuilder s = new StringBuilder();
            for ( String id : ids )
            {
                s.append( id );
                s.append( "," );
            }
            return s.substring( 0, s.length() - 1 );
        }
        return "";
    }

    private void setProperty( Properties properties, String name, String value )
    {
        if ( value != null )
        {
            properties.setProperty( name, value );
        }
    }

    public void updateArtifact( String repoId, String namespace, String projectId, String projectVersion,
                                ArtifactMetadata artifact )
    {
        File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );

        properties.setProperty( "artifact:updated:" + artifact.getId(), Long.toString(
            artifact.getFileLastModified().getTime() ) );
        properties.setProperty( "artifact:whenGathered:" + artifact.getId(), Long.toString(
            artifact.getWhenGathered().getTime() ) );
        properties.setProperty( "artifact:size:" + artifact.getId(), Long.toString( artifact.getSize() ) );
        if ( artifact.getMd5() != null )
        {
            properties.setProperty( "artifact:md5:" + artifact.getId(), artifact.getMd5() );
        }
        if ( artifact.getSha1() != null )
        {
            properties.setProperty( "artifact:sha1:" + artifact.getId(), artifact.getSha1() );
        }
        properties.setProperty( "artifact:version:" + artifact.getId(), artifact.getVersion() );

        try
        {
            writeProperties( properties, directory, PROJECT_VERSION_METADATA_KEY );
        }
        catch ( IOException e )
        {
            // TODO
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }

    private Properties readOrCreateProperties( File directory, String propertiesKey )
    {
        try
        {
            return readProperties( directory, propertiesKey );
        }
        catch ( FileNotFoundException e )
        {
            // ignore and return new properties
        }
        catch ( IOException e )
        {
            // TODO
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        return new Properties();
    }

    private Properties readProperties( File directory, String propertiesKey )
        throws IOException
    {
        Properties properties = new Properties();
        FileInputStream in = null;
        try
        {
            in = new FileInputStream( new File( directory, propertiesKey + ".properties" ) );
            properties.load( in );
        }
        finally
        {
            IOUtils.closeQuietly( in );
        }
        return properties;
    }

    public ProjectMetadata getProject( String repoId, String namespace, String projectId )
    {
        File directory = new File( getDirectory( repoId ), namespace + "/" + projectId );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );

        ProjectMetadata project = new ProjectMetadata();
        project.setNamespace( properties.getProperty( "namespace" ) );
        project.setId( properties.getProperty( "id" ) );
        return project;
    }

    public ProjectVersionMetadata getProjectVersion( String repoId, String namespace, String projectId,
                                                     String projectVersion )
    {
        File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
        String id = properties.getProperty( "id" );
        ProjectVersionMetadata versionMetadata = null;
        if ( id != null )
        {
            versionMetadata = new ProjectVersionMetadata();
            versionMetadata.setId( id );
            versionMetadata.setName( properties.getProperty( "name" ) );
            versionMetadata.setDescription( properties.getProperty( "description" ) );
            versionMetadata.setUrl( properties.getProperty( "url" ) );
            versionMetadata.setIncomplete( Boolean.valueOf( properties.getProperty( "incomplete", "false" ) ) );

            String scmConnection = properties.getProperty( "scm.connection" );
            String scmDeveloperConnection = properties.getProperty( "scm.developerConnection" );
            String scmUrl = properties.getProperty( "scm.url" );
            if ( scmConnection != null || scmDeveloperConnection != null || scmUrl != null )
            {
                Scm scm = new Scm();
                scm.setConnection( scmConnection );
                scm.setDeveloperConnection( scmDeveloperConnection );
                scm.setUrl( scmUrl );
                versionMetadata.setScm( scm );
            }

            String ciSystem = properties.getProperty( "ci.system" );
            String ciUrl = properties.getProperty( "ci.url" );
            if ( ciSystem != null || ciUrl != null )
            {
                CiManagement ci = new CiManagement();
                ci.setSystem( ciSystem );
                ci.setUrl( ciUrl );
                versionMetadata.setCiManagement( ci );
            }

            String issueSystem = properties.getProperty( "issue.system" );
            String issueUrl = properties.getProperty( "issue.url" );
            if ( issueSystem != null || issueUrl != null )
            {
                IssueManagement issueManagement = new IssueManagement();
                issueManagement.setSystem( issueSystem );
                issueManagement.setUrl( issueUrl );
                versionMetadata.setIssueManagement( issueManagement );
            }

            String orgName = properties.getProperty( "org.name" );
            String orgUrl = properties.getProperty( "org.url" );
            if ( orgName != null || orgUrl != null )
            {
                Organization org = new Organization();
                org.setName( orgName );
                org.setUrl( orgUrl );
                versionMetadata.setOrganization( org );
            }

            boolean done = false;
            int i = 0;
            while ( !done )
            {
                String licenseName = properties.getProperty( "license." + i + ".name" );
                String licenseUrl = properties.getProperty( "license." + i + ".url" );
                if ( licenseName != null || licenseUrl != null )
                {
                    License license = new License();
                    license.setName( licenseName );
                    license.setUrl( licenseUrl );
                    versionMetadata.addLicense( license );
                }
                else
                {
                    done = true;
                }
                i++;
            }

            done = false;
            i = 0;
            while ( !done )
            {
                String mailingListName = properties.getProperty( "mailingList." + i + ".name" );
                if ( mailingListName != null )
                {
                    MailingList mailingList = new MailingList();
                    mailingList.setName( mailingListName );
                    mailingList.setMainArchiveUrl( properties.getProperty( "mailingList." + i + ".archive" ) );
                    mailingList.setOtherArchives( Arrays.asList( properties.getProperty(
                        "mailingList." + i + ".otherArchives" ).split( "," ) ) );
                    mailingList.setPostAddress( properties.getProperty( "mailingList." + i + ".post" ) );
                    mailingList.setSubscribeAddress( properties.getProperty( "mailingList." + i + ".subscribe" ) );
                    mailingList.setUnsubscribeAddress( properties.getProperty( "mailingList." + i + ".unsubscribe" ) );
                    versionMetadata.addMailingList( mailingList );
                }
                else
                {
                    done = true;
                }
                i++;
            }

            done = false;
            i = 0;
            while ( !done )
            {
                String dependencyArtifactId = properties.getProperty( "dependency." + i + ".artifactId" );
                if ( dependencyArtifactId != null )
                {
                    Dependency dependency = new Dependency();
                    dependency.setArtifactId( dependencyArtifactId );
                    dependency.setGroupId( properties.getProperty( "dependency." + i + ".groupId" ) );
                    dependency.setClassifier( properties.getProperty( "dependency." + i + ".classifier" ) );
                    dependency.setOptional( Boolean.valueOf( properties.getProperty(
                        "dependency." + i + ".optional" ) ) );
                    dependency.setScope( properties.getProperty( "dependency." + i + ".scope" ) );
                    dependency.setSystemPath( properties.getProperty( "dependency." + i + ".systemPath" ) );
                    dependency.setType( properties.getProperty( "dependency." + i + ".type" ) );
                    dependency.setVersion( properties.getProperty( "dependency." + i + ".version" ) );
                    versionMetadata.addDependency( dependency );
                }
                else
                {
                    done = true;
                }
                i++;
            }

            String facetIds = properties.getProperty( "facetIds", "" );
            if ( facetIds.length() > 0 )
            {
                for ( String facetId : facetIds.split( "," ) )
                {
                    MetadataFacetFactory factory = metadataFacetFactories.get( facetId );
                    if ( factory == null )
                    {
                        log.error( "Attempted to load unknown metadata facet: " + facetId );
                    }
                    else
                    {
                        MetadataFacet facet = factory.createMetadataFacet();
                        Map<String, String> map = new HashMap<String, String>();
                        for ( Object key : new ArrayList( properties.keySet() ) )
                        {
                            String property = (String) key;
                            if ( property.startsWith( facet.getFacetId() ) )
                            {
                                map.put( property, properties.getProperty( property ) );
                            }
                        }
                        facet.fromProperties( map );
                        versionMetadata.addFacet( facet );
                    }
                }
            }

            for ( MetadataFacet facet : versionMetadata.getFacetList() )
            {
                properties.putAll( facet.toProperties() );
            }
        }
        return versionMetadata;
    }

    public Collection<String> getArtifactVersions( String repoId, String namespace, String projectId,
                                                   String projectVersion )
    {
        File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );

        Set<String> versions = new HashSet<String>();
        for ( Map.Entry entry : properties.entrySet() )
        {
            String name = (String) entry.getKey();
            if ( name.startsWith( "artifact:version:" ) )
            {
                versions.add( (String) entry.getValue() );
            }
        }
        return versions;
    }

    public Collection<ProjectVersionReference> getProjectReferences( String repoId, String namespace, String projectId,
                                                                     String projectVersion )
    {
        File directory = new File( getDirectory( repoId ), namespace + "/" + projectId + "/" + projectVersion );

        Properties properties = readOrCreateProperties( directory, PROJECT_VERSION_METADATA_KEY );
        int numberOfRefs = Integer.valueOf( properties.getProperty( "ref:lastReferenceNum", "-1" ) ) + 1;

        List<ProjectVersionReference> references = new ArrayList<ProjectVersionReference>();
        for ( int i = 0; i < numberOfRefs; i++ )
        {
            ProjectVersionReference reference = new ProjectVersionReference();
            reference.setProjectId( properties.getProperty( "ref:reference." + i + ".projectId" ) );
            reference.setNamespace( properties.getProperty( "ref:reference." + i + ".namespace" ) );
            reference.setProjectVersion( properties.getProperty( "ref:reference." + i + ".projectVersion" ) );
            reference.setReferenceType( ProjectVersionReference.ReferenceType.valueOf( properties.getProperty(
                "ref:reference." + i + ".referenceType" ) ) );
            references.add( reference );
        }
        return references;
    }

    public Collection<String> getRootNamespaces( String repoId )
    {
        return getNamespaces( repoId, null );
    }

    public Collection<String> getNamespaces( String repoId, String baseNamespace )
    {
        List<String> allNamespaces = new ArrayList<String>();
        File directory = getDirectory( repoId );
        File[] files = directory.listFiles();
        if ( files != null )
        {
            for ( File namespace : files )
            {
                if ( new File( namespace, NAMESPACE_METADATA_KEY + ".properties" ).exists() )
                {
                    allNamespaces.add( namespace.getName() );
                }
            }
        }

        Set<String> namespaces = new LinkedHashSet<String>();
        int fromIndex = baseNamespace != null ? baseNamespace.length() + 1 : 0;
        for ( String namespace : allNamespaces )
        {
            if ( baseNamespace == null || namespace.startsWith( baseNamespace + "." ) )
            {
                int i = namespace.indexOf( '.', fromIndex );
                if ( i >= 0 )
                {
                    namespaces.add( namespace.substring( fromIndex, i ) );
                }
                else
                {
                    namespaces.add( namespace.substring( fromIndex ) );
                }
            }
        }
        return new ArrayList<String>( namespaces );
    }

    public Collection<String> getProjects( String repoId, String namespace )
    {
        List<String> projects = new ArrayList<String>();
        File directory = new File( getDirectory( repoId ), namespace );
        File[] files = directory.listFiles();
        if ( files != null )
        {
            for ( File project : files )
            {
                if ( new File( project, PROJECT_METADATA_KEY + ".properties" ).exists() )
                {
                    projects.add( project.getName() );
                }
            }
        }
        return projects;
    }

    public Collection<String> getProjectVersions( String repoId, String namespace, String projectId )
    {
        List<String> projectVersions = new ArrayList<String>();
        File directory = new File( getDirectory( repoId ), namespace + "/" + projectId );
        File[] files = directory.listFiles();
        if ( files != null )
        {
            for ( File projectVersion : files )
            {
                if ( new File( projectVersion, PROJECT_VERSION_METADATA_KEY + ".properties" ).exists() )
                {
                    projectVersions.add( projectVersion.getName() );
                }
            }
        }
        return projectVersions;
    }

    private void writeProperties( Properties properties, File directory, String propertiesKey )
        throws IOException
    {
        directory.mkdirs();
        FileOutputStream os = new FileOutputStream( new File( directory, propertiesKey + ".properties" ) );
        try
        {
            properties.store( os, null );
        }
        finally
        {
            IOUtils.closeQuietly( os );
        }
    }

    public void setMetadataFacetFactories( Map<String, MetadataFacetFactory> metadataFacetFactories )
    {
        this.metadataFacetFactories = metadataFacetFactories;
    }

    public void setConfiguration( ArchivaConfiguration configuration )
    {
        this.configuration = configuration;
    }

    private static class ArtifactComparator
        implements Comparator<ArtifactMetadata>
    {
        public int compare( ArtifactMetadata artifact1, ArtifactMetadata artifact2 )
        {
            if ( artifact1.getWhenGathered() == artifact2.getWhenGathered() )
            {
                return 0;
            }
            if ( artifact1.getWhenGathered() == null )
            {
                return 1;
            }
            if ( artifact2.getWhenGathered() == null )
            {
                return -1;
            }
            return artifact1.getWhenGathered().compareTo( artifact2.getWhenGathered() );
        }
    }
}
