This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.repository.metadata;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.util.ArrayList;
023import java.util.List;
024
025import org.apache.commons.lang.StringUtils;
026import org.apache.archiva.model.ArchivaModelCloner;
027import org.apache.archiva.model.ArchivaRepositoryMetadata;
028import org.apache.archiva.model.Plugin;
029import org.apache.archiva.model.SnapshotVersion;
030
031/**
032 * RepositoryMetadataMerge 
033 *
034 *
035 */
036public class RepositoryMetadataMerge
037{
038    public static ArchivaRepositoryMetadata merge( final ArchivaRepositoryMetadata mainMetadata,
039                                                   final ArchivaRepositoryMetadata sourceMetadata )
040        throws RepositoryMetadataException
041    {
042        if ( mainMetadata == null )
043        {
044            throw new RepositoryMetadataException( "Cannot merge a null main project." );
045        }
046
047        if ( sourceMetadata == null )
048        {
049            throw new RepositoryMetadataException( "Cannot copy to a null parent project." );
050        }
051
052        ArchivaRepositoryMetadata merged = new ArchivaRepositoryMetadata();
053
054        merged.setGroupId( merge( mainMetadata.getGroupId(), sourceMetadata.getGroupId() ) );
055        merged.setArtifactId(  merge(mainMetadata.getArtifactId(), sourceMetadata.getArtifactId()));
056        merged.setVersion( merge(mainMetadata.getVersion(), sourceMetadata.getVersion()) );
057        merged.setReleasedVersion( merge( mainMetadata.getReleasedVersion(), sourceMetadata.getReleasedVersion() ) );
058        merged.setSnapshotVersion( merge( mainMetadata.getSnapshotVersion(), sourceMetadata.getSnapshotVersion() ) );
059        merged.setAvailableVersions( mergeAvailableVersions( mainMetadata.getAvailableVersions(), sourceMetadata.getAvailableVersions() ) );
060        merged.setPlugins( mergePlugins( mainMetadata.getPlugins(), sourceMetadata.getPlugins() ) );
061        
062        //Don't set if merge was not possible
063        long lastUpdated = mergeTimestamp( mainMetadata.getLastUpdated(), sourceMetadata.getLastUpdated());
064        if (lastUpdated > -1)
065        {
066            merged.setLastUpdated(  Long.toString(lastUpdated) );
067        }
068        
069        return merged;
070    }
071
072    private static boolean empty( String val )
073    {
074        if ( val == null )
075        {
076            return true;
077        }
078
079        return ( val.trim().length() <= 0 );
080    }
081    
082    private static long mergeTimestamp(String mainTimestamp, String sourceTimestamp)
083    {
084        if (sourceTimestamp == null && mainTimestamp != null)
085        {
086            return convertTimestampToLong(mainTimestamp);
087        }
088        
089        if (mainTimestamp == null && sourceTimestamp != null)
090        {
091            return convertTimestampToLong(sourceTimestamp);
092        }
093        
094        if (sourceTimestamp == null && mainTimestamp == null)
095        {
096            return -1;
097        }
098        
099        return mergeTimestamp(convertTimestampToLong(mainTimestamp), convertTimestampToLong(sourceTimestamp));
100    }
101    
102    private static long mergeTimestamp(long mainTimestamp, long sourceTimestamp)
103    { 
104        return Math.max( mainTimestamp, sourceTimestamp );
105    }
106
107    private static SnapshotVersion merge( SnapshotVersion mainSnapshotVersion, SnapshotVersion sourceSnapshotVersion )
108    {
109        if ( sourceSnapshotVersion == null )
110        {
111            return mainSnapshotVersion;
112        }
113
114        if ( mainSnapshotVersion == null )
115        {
116            return ArchivaModelCloner.clone( sourceSnapshotVersion );
117        }
118
119        SnapshotVersion merged = new SnapshotVersion();
120       
121        long mainSnapshotLastUpdated = convertTimestampToLong(mainSnapshotVersion.getTimestamp());
122        long sourceSnapshotLastUpdated = convertTimestampToLong(sourceSnapshotVersion.getTimestamp());
123                        
124        long lastUpdated = mergeTimestamp(mainSnapshotLastUpdated, sourceSnapshotLastUpdated);
125        
126        if (lastUpdated == mainSnapshotLastUpdated)
127        {
128            merged.setTimestamp(mainSnapshotVersion.getTimestamp());
129            merged.setBuildNumber(mainSnapshotVersion.getBuildNumber());
130        }
131        else
132        {
133            merged.setTimestamp(sourceSnapshotVersion.getTimestamp());
134            merged.setBuildNumber(sourceSnapshotVersion.getBuildNumber());
135        }
136
137        return merged;
138    }
139    
140    private static long convertTimestampToLong(String timestamp)
141    {
142        if (timestamp == null)
143        {
144            return -1;
145        }
146        
147        return getLongFromTimestampSafely(StringUtils.replace(timestamp, ".", ""));
148    }
149    
150    private static long getLongFromTimestampSafely( String timestampString )
151    {
152        try
153        {
154            return Long.parseLong(timestampString);
155        }
156        catch (NumberFormatException e)
157        {
158            return -1;
159        }
160    }
161
162    private static String merge( String main, String source )
163    {
164        if ( empty( main ) && !empty( source ) )
165        {
166            return source;
167        }
168
169        return main;
170    }
171    
172    private static List<Plugin> mergePlugins(List<Plugin> mainPlugins, List<Plugin> sourcePlugins)
173    {
174        if ( sourcePlugins == null )
175        {
176            return mainPlugins;
177        }
178        
179        if ( mainPlugins == null )
180        {
181            return clonePlugins( sourcePlugins );
182        }
183        
184        List<Plugin> merged = clonePlugins( mainPlugins );
185        
186        for ( Plugin plugin : sourcePlugins )
187        {
188            if ( !merged.contains( plugin ) )
189            {
190                merged.add( plugin );
191            }
192        }
193
194        return merged;
195    }
196    
197    /**
198     * Clones a list of plugins.
199     * 
200     * This method exists because ArchivaModelCloner.clonePlugins() 
201     * only works with artifact references.
202     * 
203     * @param plugins
204     * @return list of cloned plugins
205     */
206    private static List<Plugin> clonePlugins(List<Plugin> plugins)
207    {
208        if (plugins == null)
209        {
210            return null;
211        }
212        
213        List<Plugin> result = new ArrayList<>();
214        
215        for (Plugin plugin : plugins)
216        {
217            Plugin clonedPlugin = new Plugin();
218            clonedPlugin.setArtifactId(plugin.getArtifactId());
219            clonedPlugin.setName(plugin.getName());
220            clonedPlugin.setPrefix(plugin.getPrefix());
221            result.add(plugin);
222        }
223        
224        return result;
225    }
226
227    private static List<String> mergeAvailableVersions( List<String> mainAvailableVersions, List<String> sourceAvailableVersions )
228    {
229        if ( sourceAvailableVersions == null )
230        {
231            return mainAvailableVersions;
232        }
233
234        if ( mainAvailableVersions == null )
235        {
236            return ArchivaModelCloner.cloneAvailableVersions( sourceAvailableVersions );
237        }
238
239        List<String> merged = ArchivaModelCloner.cloneAvailableVersions( mainAvailableVersions );
240
241        for ( String sourceVersion : sourceAvailableVersions )
242        {
243            if ( !merged.contains( sourceVersion ) )
244            {
245                merged.add( sourceVersion );
246            }
247        }
248
249        return merged;
250    }
251}