<!--
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.
-->

<model xmlns="http://codehaus-plexus.github.io/MODELLO/1.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://codehaus-plexus.github.io/MODELLO/1.4.0 http://codehaus-plexus.github.io/modello/xsd/modello-1.4.0.xsd"
  xsd.namespace="http://maven.apache.org/METADATA/${version}"
  xml.schemaLocation="https://maven.apache.org/xsd/repository-metadata-${version}.xsd">
  <id>repository-metadata</id>
  <name>Metadata</name>
  <description><![CDATA[
    <p>Per-directory repository metadata <code>repository-metadata.xml</code>.</p>
    <p>A directory may represent 3 types of content: "groupId", "groupId/artifactId" or "groupId/artifactId/version".</p>
    <p>Most metadata content has a meaning when the directory represents a "groupId/artifactId" (<code>groupId</code>, <code>artifactId</code>, <code>versioning</code>)<p>]]>
  </description>
  <defaults>
    <default>
      <key>package</key>
      <value>org.apache.maven.artifact.repository.metadata</value>
    </default>
  </defaults>
  <classes>
    <class rootElement="true" java.clone="deep">
      <name>Metadata</name>
      <version>1.0.0+</version>
      <fields>
        <field xml.attribute="true">
          <name>modelVersion</name>
          <version>1.1.0+</version>
          <type>String</type>
          <description>The version of the underlying metadata model.</description>
        </field>
        <field>
          <name>groupId</name>
          <version>1.0.0+</version>
          <type>String</type>
          <description>The groupId when this directory represents "groupId/artifactId" or "groupId/artifactId/version".</description>
        </field>
        <field>
          <name>artifactId</name>
          <version>1.0.0+</version>
          <type>String</type>
          <description>The artifactId when this directory represents "groupId/artifactId" or "groupId/artifactId/version".</description>
        </field>
        <field>
          <name>versioning</name>
          <version>1.0.0+</version>
          <association>
            <type>Versioning</type>
          </association>
          <description>Versioning information when this directory represents "groupId/artifactId" or "groupId/artifactId/version".</description>
        </field>
        <field>
          <name>version</name>
          <version>1.0.0+</version>
          <type>String</type>
          <description><![CDATA[The base version (ie. ending in <code>-SNAPSHOT</code>) when this directory represents a "groupId/artifactId/version" for a SNAPSHOT.]]></description>
        </field>
        <field xdoc.separator="blank">
          <name>plugins</name>
          <version>1.0.0+</version>
          <description>The set of plugins when this directory represents a "groupId" (deprecated)</description>
          <annotations>
            <annotation>@Deprecated</annotation>
          </annotations>
          <association>
            <type>Plugin</type>
            <multiplicity>*</multiplicity>
          </association>
        </field>
      </fields>
      <codeSegments>
        <codeSegment>
          <version>1.0.0+</version>
          <code><![CDATA[
    private String getSnapshotVersionKey( SnapshotVersion sv )
    {
        return sv.getClassifier() + ":" + sv.getExtension();
    }

    public boolean merge( Metadata sourceMetadata )
    {
        boolean changed = false;

        for ( Plugin plugin : sourceMetadata.getPlugins() )
        {
            boolean found = false;

            for ( Plugin preExisting : getPlugins() )
            {
                if ( preExisting.getPrefix().equals( plugin.getPrefix() ) )
                {
                    found = true;
                    break;
                }
            }

            if ( !found )
            {
                Plugin mappedPlugin = new Plugin();

                mappedPlugin.setArtifactId( plugin.getArtifactId() );

                mappedPlugin.setPrefix( plugin.getPrefix() );

                mappedPlugin.setName( plugin.getName() );

                addPlugin( mappedPlugin );

                changed = true;
            }
        }

        Versioning versioning = sourceMetadata.getVersioning();
        if ( versioning != null )
        {
            Versioning v = getVersioning();
            if ( v == null )
            {
                v = new Versioning();
                setVersioning( v );
                changed = true;
            }

            for ( String version : versioning.getVersions() )
            {
                if ( !v.getVersions().contains( version ) )
                {
                    changed = true;
                    v.getVersions().add( version );
                }
            }

            if ( "null".equals( versioning.getLastUpdated() ) )
            {
                versioning.setLastUpdated( null );
            }

            if ( "null".equals( v.getLastUpdated() ) )
            {
                v.setLastUpdated( null );
            }

            if ( versioning.getLastUpdated() == null || versioning.getLastUpdated().length() == 0 )
            {
                // this should only be for historical reasons - we assume local is newer
                versioning.setLastUpdated( v.getLastUpdated() );
            }

            if ( v.getLastUpdated() == null || v.getLastUpdated().length() == 0
                 || versioning.getLastUpdated().compareTo( v.getLastUpdated() ) >= 0 )
            {
                changed = true;
                v.setLastUpdated( versioning.getLastUpdated() );

                if ( versioning.getRelease() != null )
                {
                    changed = true;
                    v.setRelease( versioning.getRelease() );
                }
                if ( versioning.getLatest() != null )
                {
                    changed = true;
                    v.setLatest( versioning.getLatest() );
                }

                Snapshot s = v.getSnapshot();
                Snapshot snapshot = versioning.getSnapshot();
                if ( snapshot != null )
                {
                    boolean updateSnapshotVersions = false;
                    if ( s == null )
                    {
                        s = new Snapshot();
                        v.setSnapshot( s );
                        changed = true;
                        updateSnapshotVersions = true;
                    }

                    // overwrite
                    if ( s.getTimestamp() == null ? snapshot.getTimestamp() != null
                        : !s.getTimestamp().equals( snapshot.getTimestamp() ) )
                    {
                        s.setTimestamp( snapshot.getTimestamp() );
                        changed = true;
                        updateSnapshotVersions = true;
                    }
                    if ( s.getBuildNumber() != snapshot.getBuildNumber() )
                    {
                        s.setBuildNumber( snapshot.getBuildNumber() );
                        changed = true;
                    }
                    if ( s.isLocalCopy() != snapshot.isLocalCopy() )
                    {
                        s.setLocalCopy( snapshot.isLocalCopy() );
                        changed = true;
                    }
                    if ( updateSnapshotVersions )
                    {
                        java.util.Map<String, SnapshotVersion> versions = new java.util.LinkedHashMap<>();
                        // never convert from legacy to new format if either source or target is legacy format
                        if ( !v.getSnapshotVersions().isEmpty() )
                        {
                            for ( SnapshotVersion sv : versioning.getSnapshotVersions() )
                            {
                                String key = getSnapshotVersionKey( sv );
                                versions.put( key, sv );
                            }
                            // never convert from legacy format
                            if ( !versions.isEmpty() )
                            {
                                for ( SnapshotVersion sv : v.getSnapshotVersions() )
                                {
                                    String key = getSnapshotVersionKey( sv );
                                    if ( !versions.containsKey( key ) )
                                    {
                                        versions.put( key, sv );
                                    }
                                }
                            }
                            v.setSnapshotVersions( new java.util.ArrayList<SnapshotVersion>( versions.values() ) );
                        }

                        changed = true;
                    }
                }
            }
        }
        return changed;
    }
          ]]></code>
        </codeSegment>
      </codeSegments>
    </class>
    <class java.clone="deep">
      <name>Versioning</name>
      <version>1.0.0+</version>
      <description>Versioning information for "groupId/artifactId" or "groupId/artifactId/version" SNAPSHOT</description>
      <fields>
        <field>
          <name>latest</name>
          <version>1.0.0+</version>
          <type>String</type>
          <description>What the last version added to the directory is, including both releases and snapshots ("groupId/artifactId" directory only)</description>
        </field>
        <field>
          <name>release</name>
          <version>1.0.0+</version>
          <type>String</type>
          <description>What the last version added to the directory is, for the releases only ("groupId/artifactId" directory only)</description>
        </field>
        <field>
          <name>versions</name>
          <version>1.0.0+</version>
          <description>Versions available of the artifact (both releases and snapshots) ("groupId/artifactId" directory only)</description>
          <association>
            <type>String</type>
            <multiplicity>*</multiplicity>
          </association>
        </field>
        <field xdoc.separator="blank">
          <name>lastUpdated</name>
          <version>1.0.0+</version>
          <type>String</type>
          <description>When the metadata was last updated (both "groupId/artifactId" and "groupId/artifactId/version" directories). The timestamp is expressed using UTC in the format yyyyMMddHHmmss.</description>
        </field>
        <field xdoc.separator="blank">
          <name>snapshot</name>
          <version>1.0.0+</version>
          <association>
            <type>Snapshot</type>
          </association>
          <description>The current snapshot data in use for this version ("groupId/artifactId/version" only)</description>
        </field>
        <field>
          <name>snapshotVersions</name>
          <version>1.1.0+</version>
          <description>Information for each sub-artifact available in this artifact snapshot. This is only the most recent SNAPSHOT for each unique extension/classifier combination.</description>
          <association>
            <type>SnapshotVersion</type>
            <multiplicity>*</multiplicity>
          </association>
        </field>
      </fields>
      <codeSegments>
        <codeSegment>
          <version>1.0.0+</version>
          <code><![CDATA[
    public void updateTimestamp()
    {
        setLastUpdatedTimestamp( new java.util.Date() );
    }

    public void setLastUpdatedTimestamp( java.util.Date date )
    {
        java.util.TimeZone timezone = java.util.TimeZone.getTimeZone( "UTC" );
        java.text.DateFormat fmt = new java.text.SimpleDateFormat( "yyyyMMddHHmmss" );
        fmt.setTimeZone( timezone );
        setLastUpdated( fmt.format( date ) );
    }
          ]]></code>
        </codeSegment>
      </codeSegments>
    </class>
    <class java.clone="deep">
      <name>Snapshot</name>
      <version>1.0.0+</version>
      <description>Snapshot data for the last artifact corresponding to the SNAPSHOT base version</description>
      <fields>
        <field>
          <name>timestamp</name>
          <version>1.0.0+</version>
          <description>The timestamp when this version was deployed. The timestamp is expressed using UTC in the format yyyyMMdd.HHmmss.</description>
          <type>String</type>
        </field>
        <field>
          <name>buildNumber</name>
          <version>1.0.0+</version>
          <description>The incremental build number</description>
          <type>int</type>
        </field>
        <field>
          <name>localCopy</name>
          <version>1.0.0+</version>
          <description>Whether to use a local copy instead (with filename that includes the base version)</description>
          <type>boolean</type>
          <defaultValue>false</defaultValue>
        </field>
      </fields>
    </class>
    <class java.clone="deep">
      <name>SnapshotVersion</name>
      <version>1.1.0+</version>
      <description>Versioning information for a sub-artifact of the current snapshot artifact.</description>
      <fields>
        <field>
          <name>classifier</name>
          <version>1.1.0+</version>
          <type>String</type>
          <description>The classifier of the sub-artifact. Each classifier and extension pair may only appear once.</description>
          <defaultValue></defaultValue>
          <identifier>true</identifier>
        </field>
        <field>
          <name>extension</name>
          <version>1.1.0+</version>
          <type>String</type>
          <description>The file extension of the sub-artifact. Each classifier and extension pair may only appear once.</description>
          <identifier>true</identifier>
        </field>
        <field xml.tagName="value">
          <name>version</name>
          <version>1.1.0+</version>
          <type>String</type>
          <description>The resolved snapshot version of the sub-artifact.</description>
          <identifier>true</identifier>
        </field>
        <field>
          <name>updated</name>
          <version>1.1.0+</version>
          <type>String</type>
          <description>The timestamp when this version information was last updated. The timestamp is expressed using UTC in the format yyyyMMddHHmmss.</description>
          <identifier>true</identifier>
        </field>
      </fields>
    </class>

    <class java.clone="deep">
      <name>Plugin</name>
      <version>1.0.0+</version>
      <description>Mapping information for a single plugin within this group (deprecated).</description>
      <annotations>
        <annotation>@Deprecated</annotation>
      </annotations>
      <comment>NOTE: plugin version is _NOT_ included here, since it is resolved using a separate algorithm in plugins' artifact.</comment>
      <fields>
        <field>
          <name>name</name>
          <type>String</type>
          <required>true</required>
          <version>1.0.0+</version>
          <description>Display name for the plugin.</description>
        </field>
        <field>
          <name>prefix</name>
          <type>String</type>
          <required>true</required>
          <version>1.0.0+</version>
          <description>The plugin invocation prefix (i.e. eclipse for eclipse:eclipse)</description>
        </field>
        <field>
          <name>artifactId</name>
          <type>String</type>
          <required>true</required>
          <version>1.0.0+</version>
          <description>The plugin artifactId</description>
        </field>
      </fields>
    </class>
  </classes>
</model>
