package org.jfrog.build.extractor.maven;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.util.*;
/**
* Helper class for merging JSON data.
*/
class JsonMergeHelper
{
String[] mapIdentifiers;
JsonMergeHelper ( String ... mapIdentifiers )
{
this.mapIdentifiers = mapIdentifiers;
}
String objectToJson ( Object o ) {
try {
return new ObjectMapper().writer().withDefaultPrettyPrinter().writeValueAsString( o );
}
catch ( Exception e ) {
throw new RuntimeException( String.format( "Failed to convert object '%s' to JSON", o ), e );
}
}
<T> T jsonToObject ( String jsonContent, Class<T> type ) {
try {
return new ObjectMapper().reader( type ).readValue( jsonContent );
}
catch ( Exception e ) {
throw new RuntimeException( String.format( "Failed to convert JSON '%s' to object", jsonContent ), e );
}
}
<T> T jsonToObject ( File jsonFile, Class<T> type ) {
try {
return new ObjectMapper().reader( type ).readValue( jsonFile );
}
catch ( Exception e ) {
throw new RuntimeException( String.format( "Failed to convert JSON file '%s' to object", jsonFile ), e );
}
}
Map<String, ?> mergeAndWrite ( Map<String, ?> source, Map<String, ?> destination, File destinationFile )
{
return jsonWrite( mergeMaps( source, destination ), destinationFile );
}
<T> List<T> mergeAndWrite ( List<T> source, List<T> destination, File destinationFile )
{
return jsonWrite( mergeLists( source, destination ), destinationFile );
}
String mergeJsons( String source, String destination ) {
Object sourceObject = jsonToObject( source, Object.class );
Object destinationObject = jsonToObject( destination, Object.class );
Object mergedObject =
(( sourceObject instanceof Map ) && ( destinationObject instanceof Map )) ? mergeMaps(( Map ) sourceObject, ( Map ) destinationObject ) :
(( sourceObject instanceof List ) && ( destinationObject instanceof List )) ? mergeLists(( List ) sourceObject, ( List ) destinationObject ) :
null;
if ( mergedObject == null ) {
throw new RuntimeException( String.format( "Unable to merge JSON content of '%s' and '%s'", source, destination ));
}
return objectToJson( mergedObject );
}
Map<String,?> mergeMaps ( Map<String, ?> source, Map<String, ?> destination ){
if (( source == null ) || source.isEmpty()){ return destination; }
if (( destination == null ) || destination.isEmpty()){ return source; }
if ( source.equals( destination )){ return source; }
Map<String,Object> result = new HashMap<String,Object>( destination );
for ( Map.Entry<String,?> entry : source.entrySet()) {
String sourceKey = entry.getKey();
Object sourceValue = entry.getValue();
Object mergedValue = ( sourceValue instanceof List ) ? mergeLists(( List ) sourceValue, ( List ) result.get( sourceKey )) :
( sourceValue instanceof Map ) ? mergeMaps(( Map ) sourceValue, ( Map ) result.get( sourceKey )) :
sourceValue;
result.put( sourceKey, mergedValue );
}
return result;
}
<T> List<T> mergeLists ( List<T> source, List<T> destination )
{
if (( source == null ) || source.isEmpty()){ return destination; }
if (( destination == null ) || destination.isEmpty()){ return source; }
if ( source.equals( destination )){ return source; }
if ( source.get( 0 ) instanceof Map ) {
Map map = ( Map ) source.get( 0 );
for ( String mapIdentifier : mapIdentifiers )
{
if ( map.get( mapIdentifier ) != null ) {
return ( List<T> ) mergeListsOfMaps(( List<Map<String, ?>> ) source, ( List<Map<String, ?>> ) destination, mapIdentifier );
}
}
}
List<T> result = new ArrayList<T>( destination );
result.addAll( source );
return new ArrayList<T>( new HashSet<T>( result ));
}
private <T> T jsonWrite ( T object, File destinationFile )
{
try {
FileUtils.write( destinationFile, objectToJson( object ), "UTF-8" );
return object;
}
catch ( Exception e ) {
throw new RuntimeException( String.format( "Failed to write [%s] to [%s]", object, destinationFile ), e );
}
}
private List<Map<String,?>> mergeListsOfMaps ( List<Map<String, ?>> source, List<Map<String, ?>> destination, String mapIdentifier )
{
if (( source == null ) || source.isEmpty()){ return destination; }
if (( destination == null ) || destination.isEmpty()){ return source; }
if ( source.equals( destination )){ return source; }
List<Map<String,?>> result = new ArrayList<Map<String, ?>>( Math.max( source.size(), destination.size()));
for ( Map<String,?> sourceMap: new ArrayList<Map<String, ?>>( source )) {
boolean matchingMapFound = false;
String sourceMapId = ( String ) sourceMap.get( mapIdentifier );
for ( Map<String,?> destinationMap: new ArrayList<Map<String, ?>>( destination )) {
if ( ! matchingMapFound ){
String destinationMapId = ( String ) destinationMap.get( mapIdentifier );
if ( sourceMapId.equals( destinationMapId )) {
matchingMapFound = true;
result.add( mergeMaps( sourceMap, destinationMap ));
source.remove( sourceMap );
destination.remove( destinationMap );
}
}
}
}
result.addAll( destination );
result.addAll( source );
return result;
}
}