/**
 * Copyright (c) 2014 Gang Ling.
 *
 *   Licensed 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.
 *
*/
package org.spdx.merge;

import java.util.ArrayList;
import java.util.Arrays;
import org.spdx.rdfparser.DOAPProject;
import org.spdx.rdfparser.InvalidSPDXAnalysisException;
import org.spdx.rdfparser.SPDXDocument;
import org.spdx.rdfparser.SPDXFile;

/**
 * Application to merge SPDX files information into one unique result. 
 * @author Gang Ling
 *
 */

public class SpdxFileInfoMerger{
	
	private SPDXDocument master = null;
	public SpdxFileInfoMerger(SPDXDocument masterDoc){
		this.master = masterDoc;
	}
	/**
	 * 
	 * @param mergeDocs
	 * @return mergeFileInfo
	 * @throws InvalidSPDXAnalysisException
	 */
	public SPDXFile[] mergeFileInfo(SPDXDocument[] subDocs)throws InvalidSPDXAnalysisException{
			
	        //an array to store an deep copy of file information from master document.
			SPDXFile[] masterFileInfo = master.getSpdxPackage().getFiles();
			
			//convert masterFileInfo array into an arrayList which will be returned to main class at end
			ArrayList<SPDXFile> retval = new ArrayList<SPDXFile>(Arrays.asList(cloneFiles(masterFileInfo)));
			
			SpdxLicenseMapper mapper = new SpdxLicenseMapper(master);
			
			for(int q = 0; q < subDocs.length; q++){
				//an array to store an deep copy of file information from current child document
				SPDXFile[] subFileInfo = cloneFiles(subDocs[q].getSpdxPackage().getFiles());
				
				for(int k = 0; k < retval.size(); k++){
					boolean foundNameMatch = false;
					boolean foundSha1Match = false;
					
					//determine if any file name matched
					for(int p = 0; p < subFileInfo.length; p++){
						if(retval.get(k).getName().equalsIgnoreCase(subFileInfo[p].getName())){
							foundNameMatch = true;
						}
						//determine if any checksum matched
						if(retval.get(k).getSha1().equals(subFileInfo[p].getSha1())){
							foundSha1Match = true;
						}
						//if both name and checksum are not matched, then check the license Ids from child files 
						if(!foundNameMatch && !foundSha1Match){
							//check whether licIdMap has this particular child document  
							if(mapper.docInNonStdLicIdMap(subDocs[q])){
								mapper.replaceNonStdLicInFile(subDocs[q], subFileInfo[p]);
								retval.add(subFileInfo[p]);
							}else{
								retval.add(subFileInfo[p]);
							}
						}else{
							//if both name and checksum are matched, then merge the DOAPProject information
							//still need to figure out how to solve the issue if license and other information is not exactly the same
							boolean foundMasterDOAP = false;
							boolean foundChildDOAP = false;
						    if(checkDOAPProject(retval.get(k))){
						    	foundMasterDOAP = true;
						    }
						    if(checkDOAPProject(subFileInfo[p])){
						    	foundChildDOAP = true;
						    }
						    if(foundMasterDOAP && foundChildDOAP){
						    	DOAPProject[] masterArtifactOf = cloneDOAPProject(retval.get(k).getArtifactOf());
						    	DOAPProject[] subArtifactOfA = cloneDOAPProject(subFileInfo[p].getArtifactOf());
						    	DOAPProject[] mergedArtifactOf = mergeDOAPInfo(masterArtifactOf, subArtifactOfA);
						    	retval.get(k).setArtifactOf(mergedArtifactOf);//assume the setArtifactOf() runs as over-write data
						    	
						    }
						    //if master doesn't have DOAPProject information but sub file has 
						    if(!foundMasterDOAP && foundChildDOAP){
						    	DOAPProject[] childArtifactOfB = cloneDOAPProject(subFileInfo[p].getArtifactOf());
						    	retval.get(k).setArtifactOf(childArtifactOfB);//assume add artifact and Homepage at same time
						    }
						}
					}
				}
			}
		SPDXFile[] fileMergeResult = new SPDXFile[retval.size()];
		retval.toArray(fileMergeResult);
		retval.clear();
		return fileMergeResult;
	}
		
	/**
	 * 
	 * @param spdxFile
	 * @return foundDOAPProject
	 */
	public boolean checkDOAPProject (SPDXFile spdxFile){
		boolean foundDOAPProject = false;
		if(spdxFile.getArtifactOf() != null && spdxFile.getArtifactOf().length > 0){
			foundDOAPProject = true;
		}
		return foundDOAPProject;
	}
	
	/**
	 * 
	 * @param MasterArtifactOf
	 * @param subArtifactOfA
	 * @return mergedArtfactOf
	 */
	public DOAPProject[] mergeDOAPInfo(DOAPProject[] MasterArtifactOf, DOAPProject[] subArtifactOfA){
		ArrayList<DOAPProject> retval = new ArrayList<DOAPProject>(Arrays.asList(MasterArtifactOf));
		for(int l = 0; l < subArtifactOfA.length; l++){
			retval.add(subArtifactOfA[l]);//assume add all DOAPProject include both artifactOf and Homepage
		}
		DOAPProject[] mergedArtifactOf = new DOAPProject[retval.size()];
		retval.toArray(mergedArtifactOf);
		retval.clear();
		return mergedArtifactOf;
	}
	
	/**
	 * 
	 * @param orgFilesArray
	 * @return clonedFilesArray
	 */
	public SPDXFile[] cloneFiles(SPDXFile[] orgFilesArray){
		SPDXFile[] clonedFilesArray = new SPDXFile[orgFilesArray.length];
		for(int h = 0; h < orgFilesArray.length; h++){
			clonedFilesArray[h] = orgFilesArray[h].clone();
		}
		return clonedFilesArray;
	}
	
	/**
	 * 
	 * @param orgProjectArray
	 * @return clonedProjectArray
	 */
	public DOAPProject[] cloneDOAPProject(DOAPProject[] orgProjectArray){
		DOAPProject[] clonedProjectArray = new DOAPProject[orgProjectArray.length];
		for(int j = 0; j < orgProjectArray.length; j++){
			clonedProjectArray[j] = orgProjectArray[j].clone();
		}
		return clonedProjectArray;		
	}
}

@@ -690,16 +690,17 @@
 Arrays;%0A
+%0A
 import o
@@ -826,16 +826,68 @@
 cument;%0A
+import org.spdx.rdfparser.SPDXDocument.SPDXPackage;%0A
 import o
@@ -1068,31 +1068,35 @@
 ate SPDX
-Document master
+Package packageInfo
  = null;
@@ -1131,54 +1131,74 @@
 SPDX
-Document masterDoc)%7B%0A%09%09this.master = masterDoc
+Package packageInfoResult)%7B%0A%09%09this.packageInfo = packageInfoResult
 ;%0A%09%7D
@@ -1517,31 +1517,19 @@
 o = 
-master.getSpdxP
+p
 ackage
-()
+Info
 .get
@@ -1741,16 +1741,16 @@
 ));%0A%09%09%09%0A
+
 %09%09%09SpdxL
@@ -1793,22 +1793,16 @@
 eMapper(
-master
 );%0A%09%09%09%0A%09

change pass in paramater to SPDXPackage packageInfoResult in constructor