This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.repository.metadata.base;
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 org.apache.archiva.model.ArchivaModelCloner;
023import org.apache.archiva.model.ArchivaRepositoryMetadata;
024import org.apache.archiva.model.Plugin;
025import org.apache.archiva.model.SnapshotVersion;
026import org.apache.archiva.repository.metadata.RepositoryMetadataException;
027import org.apache.commons.lang3.StringUtils;
028
029import java.util.ArrayList;
030import java.util.List;
031
032/**
033 * RepositoryMetadataMerge 
034 *
035 *
036 */
037public class RepositoryMetadataMerge
038{
039    public static ArchivaRepositoryMetadata merge( final ArchivaRepositoryMetadata mainMetadata,
040                                                   final ArchivaRepositoryMetadata sourceMetadata )
041        throws RepositoryMetadataException
042    {
043        if ( mainMetadata == null )
044        {
045            throw new RepositoryMetadataException( "Cannot merge a null main project." );
046        }
047
048        if ( sourceMetadata == null )
049        {
050            throw new RepositoryMetadataException( "Cannot copy to a null parent project." );
051        }
052
053        ArchivaRepositoryMetadata merged = new ArchivaRepositoryMetadata();
054
055        merged.setGroupId( merge( mainMetadata.getGroupId(), sourceMetadata.getGroupId() ) );
056        merged.setArtifactId(  merge(mainMetadata.getArtifactId(), sourceMetadata.getArtifactId()));
057        merged.setVersion( merge(mainMetadata.getVersion(), sourceMetadata.getVersion()) );
058        merged.setReleasedVersion( merge( mainMetadata.getReleasedVersion(), sourceMetadata.getReleasedVersion() ) );
059        merged.setSnapshotVersion( merge( mainMetadata.getSnapshotVersion(), sourceMetadata.getSnapshotVersion() ) );
060        merged.setAvailableVersions( mergeAvailableVersions( mainMetadata.getAvailableVersions(), sourceMetadata.getAvailableVersions() ) );
061        merged.setPlugins( mergePlugins( mainMetadata.getPlugins(), sourceMetadata.getPlugins() ) );
062        
063        //Don't set if merge was not possible
064        long lastUpdated = mergeTimestamp( mainMetadata.getLastUpdated(), sourceMetadata.getLastUpdated());
065        if (lastUpdated > -1)
066        {
067            merged.setLastUpdated(  Long.toString(lastUpdated) );
068        }
069        
070        return merged;
071    }
072
073    private static boolean empty( String val )
074    {
075        if ( val == null )
076        {
077            return true;
078        }
079
080        return ( val.trim().length() <= 0 );
081    }
082    
083    private static long mergeTimestamp(String mainTimestamp, String sourceTimestamp)
084    {
085        if (sourceTimestamp == null && mainTimestamp != null)
086        {
087            return convertTimestampToLong(mainTimestamp);
088        }
089        
090        if (mainTimestamp == null && sourceTimestamp != null)
091        {
092            return convertTimestampToLong(sourceTimestamp);
093        }
094        
095        if (sourceTimestamp == null && mainTimestamp == null)
096        {
097            return -1;
098        }
099        
100        return mergeTimestamp(convertTimestampToLong(mainTimestamp), convertTimestampToLong(sourceTimestamp));
101    }
102    
103    private static long mergeTimestamp(long mainTimestamp, long sourceTimestamp)
104    { 
105        return Math.max( mainTimestamp, sourceTimestamp );
106    }
107
108    private static SnapshotVersion merge( SnapshotVersion mainSnapshotVersion, SnapshotVersion sourceSnapshotVersion )
109    {
110        if ( sourceSnapshotVersion == null )
111        {
112            return mainSnapshotVersion;
113        }
114
115        if ( mainSnapshotVersion == null )
116        {
117            return ArchivaModelCloner.clone( sourceSnapshotVersion );
118        }
119
120        SnapshotVersion merged = new SnapshotVersion();
121       
122        long mainSnapshotLastUpdated = convertTimestampToLong(mainSnapshotVersion.getTimestamp());
123        long sourceSnapshotLastUpdated = convertTimestampToLong(sourceSnapshotVersion.getTimestamp());
124                        
125        long lastUpdated = mergeTimestamp(mainSnapshotLastUpdated, sourceSnapshotLastUpdated);
126        
127        if (lastUpdated == mainSnapshotLastUpdated)
128        {
129            merged.setTimestamp(mainSnapshotVersion.getTimestamp());
130            merged.setBuildNumber(mainSnapshotVersion.getBuildNumber());
131        }
132        else
133        {
134            merged.setTimestamp(sourceSnapshotVersion.getTimestamp());
135            merged.setBuildNumber(sourceSnapshotVersion.getBuildNumber());
136        }
137
138        return merged;
139    }
140    
141    private static long convertTimestampToLong(String timestamp)
142    {
143        if (timestamp == null)
144        {
145            return -1;
146        }
147        
148        return getLongFromTimestampSafely(StringUtils.replace(timestamp, ".", ""));
149    }
150    
151    private static long getLongFromTimestampSafely( String timestampString )
152    {
153        try
154        {
155            return Long.parseLong(timestampString);
156        }
157        catch (NumberFormatException e)
158        {
159            return -1;
160        }
161    }
162
163    private static String merge( String main, String source )
164    {
165        if ( empty( main ) && !empty( source ) )
166        {
167            return source;
168        }
169
170        return main;
171    }
172    
173    private static List<Plugin> mergePlugins(List<Plugin> mainPlugins, List<Plugin> sourcePlugins)
174    {
175        if ( sourcePlugins == null )
176        {
177            return mainPlugins;
178        }
179        
180        if ( mainPlugins == null )
181        {
182            return clonePlugins( sourcePlugins );
183        }
184        
185        List<Plugin> merged = clonePlugins( mainPlugins );
186        
187        for ( Plugin plugin : sourcePlugins )
188        {
189            if ( !merged.contains( plugin ) )
190            {
191                merged.add( plugin );
192            }
193        }
194
195        return merged;
196    }
197    
198    /**
199     * Clones a list of plugins.
200     * 
201     * This method exists because ArchivaModelCloner.clonePlugins() 
202     * only works with artifact references.
203     * 
204     * @param plugins
205     * @return list of cloned plugins
206     */
207    private static List<Plugin> clonePlugins(List<Plugin> plugins)
208    {
209        if (plugins == null)
210        {
211            return null;
212        }
213        
214        List<Plugin> result = new ArrayList<>();
215        
216        for (Plugin plugin : plugins)
217        {
218            Plugin clonedPlugin = new Plugin();
219            clonedPlugin.setArtifactId(plugin.getArtifactId());
220            clonedPlugin.setName(plugin.getName());
221            clonedPlugin.setPrefix(plugin.getPrefix());
222            result.add(plugin);
223        }
224        
225        return result;
226    }
227
228    private static List<String> mergeAvailableVersions( List<String> mainAvailableVersions, List<String> sourceAvailableVersions )
229    {
230        if ( sourceAvailableVersions == null )
231        {
232            return mainAvailableVersions;
233        }
234
235        if ( mainAvailableVersions == null )
236        {
237            return ArchivaModelCloner.cloneAvailableVersions( sourceAvailableVersions );
238        }
239
240        List<String> merged = ArchivaModelCloner.cloneAvailableVersions( mainAvailableVersions );
241
242        for ( String sourceVersion : sourceAvailableVersions )
243        {
244            if ( !merged.contains( sourceVersion ) )
245            {
246                merged.add( sourceVersion );
247            }
248        }
249
250        return merged;
251    }
252}