/// <summary> /// Files Comparison of Comparator /// </summary> /// <param name="result">SyncResult Object to catch Exception Thrown</param> /// <param name="resultAlbum">Result Album to Store Result</param> /// <param name="sourceAlbum">Source Album being Compared</param> /// <param name="targetAlbum">Target Album being Compared</param> private void compareFiles(SyncResult result, Album[] resultAlbum, Album sourceAlbum, Album targetAlbum) { try { /* Get the necessary Metadatas and Files (in string) */ List<Files> sourceMetadata = sourceAlbum.getMetadata(); // S' List<Files> targetMetadata = targetAlbum.getMetadata(); // T' List<string> sourceFiles = getFilesFromPath(sourceAlbum.getPath()); // S List<string> targetFiles = getFilesFromPath(targetAlbum.getPath()); // T /* Merge the Lists into a single List containing all filename (in string) */ List<string> listUnion = mergeLists(sourceAlbum.getPath(), targetAlbum.getPath(), sourceFiles, targetFiles, sourceMetadata, targetMetadata); /* Boolean values for Comparison Logic: */ bool sOne; // File exist in S bool tOne; // File exist in T bool sTwo; // File exist in S' bool tTwo; // File exist in T' bool sS; // S.File == S'.File bool tT; // T.File == T'.File bool ST; // S.File == T.File /* Comparison Logic: */ foreach (string filenames in listUnion) { String filename = filenames; //Console.WriteLine("file: " + filename); if (filename.Contains(PATH_DELIMITER)) { filename = filename.Replace(PATH_DELIMITER, ""); } /* Get the boolean values for the first 4 variables: */ sOne = isFileExist(Album.combinePath(sourceAlbum.getPath(), filename), sourceFiles); // Source FileSystem (S) Exist tOne = isFileExist(Album.combinePath(targetAlbum.getPath(), filename), targetFiles); // Target FileSystem (T) Exist sTwo = isFileExist(Album.combinePath(sourceAlbum.getPath(), filename), sourceMetadata); // Source Metadata (S') Exist tTwo = isFileExist(Album.combinePath(targetAlbum.getPath(), filename), targetMetadata); // Target Metadata (T') Exist /* Envelope Check: */ // To Check: Use Binary of the form sOne sTwo tOne tTwo // e.g.: if true true false true -> 1101 = 13 if (sOne && sTwo && tOne && tTwo) // 1111 = 15 { /* Get boolean for sS tT ST */ Files sourceMTDT = getPhotoFromFilename(sourceMetadata, filename); Files targetMTDT = getPhotoFromFilename(targetMetadata, filename); // Use Factory Method Pattern Files sourceFile = Files.getFilesObject(Album.combinePath(sourceAlbum.getPath(), filename)); Files targetFile = Files.getFilesObject(Album.combinePath(targetAlbum.getPath(), filename)); // Check Files Read and Write Access if (sourceFile == null || targetFile == null) continue; sS = sourceFile.equals(sourceMTDT); tT = targetFile.equals(targetMTDT); ST = sourceFile.equals(targetFile); /* Inner Check: */ if (sS && tT && ST) // 111 = 7 { // EQUAL: Ignore continue; } else if (sS && tT && !ST) // 110 = 6 { /* Check for Modification Date and File Size */ checkModificationDate(resultAlbum, sourceFile, targetFile); continue; } else if (sS && !tT && ST) // 101 = 5 { // UPDATE T' targetMTDT.update(targetFile); continue; } else if (sS && !tT && !ST) // 100 = 4 { // TARGET IS NEWER: Add target file to resultAlbum[TARGET_LATEST] resultAlbum[TARGET_LATEST].add(targetFile); continue; } else if (!sS && tT && ST) // 011 = 3 { // UPDATE S' sourceMTDT.update(sourceFile); continue; } else if (!sS && tT && !ST) // 010 = 2 { // SOURCE IS NEWER: Add source file to resultAlbum[SOURCE_LATEST] resultAlbum[SOURCE_LATEST].add(sourceFile); continue; } else if (!sS && !tT && ST) // 001 = 1 { // UPDATE S' & UPDATE T' sourceMTDT.update(sourceFile); targetMTDT.update(targetFile); continue; } else // 000 = 0 { // CONFLICT FILE: Add source file to resultAlbum[SOURCE_CONFLICT] // Add target file to resultAlbum[TARGET_CONFLICT] resultAlbum[SOURCE_CONFLICT].add(sourceFile); resultAlbum[TARGET_CONFLICT].add(targetFile); continue; } } else if (sOne && sTwo && !tOne && tTwo) // 1101 = 13 { /* Get boolean for sS tT ST */ Files sourceMTDT = getPhotoFromFilename(sourceMetadata, filename); // Use Factory Method Pattern //Files sourceFile = new Photo(Album.combinePath(sourceAlbum.getPath(), filename)); Files sourceFile = Files.getFilesObject(Album.combinePath(sourceAlbum.getPath(), filename)); // Check Files Read and Write Access if (sourceFile == null) continue; sS = sourceFile.equals(sourceMTDT); if (sS) { // TARGET IS DELETED: Add source file to resultAlbum[SOURCE_DELETE] targetAlbum.trim(Album.combinePath(targetAlbum.getPath(), filename), Album.TRIM_METADATA); resultAlbum[SOURCE_DELETE].add(sourceFile); continue; } else { // SOURCE IS CHANGED: Takes precedence over deletion // Add source to resultAlbum[SOURCE_LATEST]; resultAlbum[SOURCE_LATEST].add(sourceFile); continue; } } else if (sOne && !sTwo && tOne && !tTwo) // 1010 = 10 { /* Get boolean for ST */ // Use Factory Method Pattern //Files sourceFile = new Photo(Album.combinePath(sourceAlbum.getPath(), filename)); //Files targetFile = new Photo(Album.combinePath(targetAlbum.getPath(), filename)); Files sourceFile = Files.getFilesObject(Album.combinePath(sourceAlbum.getPath(), filename)); Files targetFile = Files.getFilesObject(Album.combinePath(targetAlbum.getPath(), filename)); // Check Files Read and Write Access if (sourceFile == null || targetFile == null) continue; ST = sourceFile.equals(targetFile); /* Inner Check: */ if (!ST) // 0 { /* Check for Modification Date and File Size: */ checkModificationDate(resultAlbum, sourceFile, targetFile); } /* CREATE S' & CREATE T' */ sourceAlbum.add(sourceFile); targetAlbum.add(targetFile); continue; } else if (sOne && !sTwo && !tOne && !tTwo) // 1000 = 08 { // SOURCE IS NEWER: Add source file to resultAlbum[SOURCE_LATEST] // Use Factory Method Pattern Files sourceFile = Files.getFilesObject(Album.combinePath(sourceAlbum.getPath(), filename)); Files targetFile = Files.getFilesObject(Album.combinePath(sourceAlbum.getPath(), filename)); // Check Files Read and Write Access if (sourceFile == null || targetFile == null) continue; targetFile.setFullpath(Album.combinePath(targetAlbum.getPath(), filename)); resultAlbum[SOURCE_LATEST].add(sourceFile); /* CREATE S' & CREATE T' */ sourceAlbum.add(sourceFile); targetAlbum.add(targetFile); continue; } else if (!sOne && sTwo && tOne && tTwo) // 0111 = 07 { /* Get boolean for sS tT ST */ Files targetMTDT = getPhotoFromFilename(targetMetadata, filename); // Use Factory Method Pattern Files targetFile = Files.getFilesObject(Album.combinePath(targetAlbum.getPath(), filename)); // Check Files Read and Write Access if (targetFile == null) continue; tT = targetFile.equals(targetMTDT); if (tT) { // SOURCE IS DELETED: Add target file to resultAlbum[TARGET_DELETE] sourceAlbum.trim(Album.combinePath(sourceAlbum.getPath(), filename), Album.TRIM_METADATA); resultAlbum[TARGET_DELETE].add(targetFile); continue; } else { // TARGET IS CHANGED: Takes precedence over deletion // Add to resultAlbum[TARGET_LATEST] resultAlbum[TARGET_LATEST].add(targetFile); continue; } } else if (!sOne && sTwo && !tOne && tTwo) // 0101 = 05 { Files sourceMTDT = getPhotoFromFilename(sourceMetadata, filename); Files targetMTDT = getPhotoFromFilename(targetMetadata, filename); // REMOVE S' REMOVE T' sourceAlbum.trim(Album.combinePath(sourceAlbum.getPath(), filename), Album.TRIM_METADATA); targetAlbum.trim(Album.combinePath(targetAlbum.getPath(), filename), Album.TRIM_METADATA); continue; } else if (!sOne && !sTwo && tOne && !tTwo) // 0010 = 02 { // TARGET IS NEWER: Add target file to resultAlbum[TARGET_LATEST] // Use Factory Method Pattern Files targetFile = Files.getFilesObject(Album.combinePath(targetAlbum.getPath(), filename)); Files sourceFile = Files.getFilesObject(Album.combinePath(targetAlbum.getPath(), filename)); // Check Files Read and Write Access if (targetFile == null || sourceFile == null) continue; sourceFile.setFullpath(Album.combinePath(sourceAlbum.getPath(), filename)); resultAlbum[TARGET_LATEST].add(targetFile); /* CREATE S' & CREATE T' */ sourceAlbum.add(sourceFile); targetAlbum.add(targetFile); continue; } else // 1110 = 14 ; 1101 = 12 ; 1011 = 11 // 1001 = 09 ; 0110 = 06 ; 0100 = 04 // 0011 = 03 ; 0001 = 01 ; 0000 = 00 { throw new Exception(INVALID_FILES); } } } catch (Exception e) { result.uaeThrown(); } }
/// <summary> /// Folders Comparison of Comparator /// </summary> /// <param name="result"></param> /// <param name="resultAlbum"></param> /// <param name="recursive"></param> /// <param name="sourceAlbum"></param> /// <param name="targetAlbum"></param> private void compareFolders(SyncResult result, Album[] resultAlbum, Stack<CompareStackContent> recursive, Album sourceAlbum, Album targetAlbum) { try { /* Get the Necessary Metadata and Folder Info */ List<string> sourceSubFolders = getSubFoldersFromPath(sourceAlbum.getPath()); List<string> targetSubFolders = getSubFoldersFromPath(targetAlbum.getPath()); List<Album> sourceSubAlbums = sourceAlbum.getSubAlbum(); List<Album> targetSubAlbums = targetAlbum.getSubAlbum(); /* Merge into a Single List */ List<string> allSubFolders = mergeLists(sourceAlbum.getPath(), targetAlbum.getPath(), sourceSubFolders, targetSubFolders, sourceSubAlbums, targetSubAlbums); Album newSource, newTarget; foreach (string subName in allSubFolders) { bool SF = isFileExist(subName, sourceSubFolders); bool TF = isFileExist(subName, targetSubFolders); bool SA = isFileExist(subName, sourceSubAlbums); bool TA = isFileExist(subName, targetSubAlbums); if (SF && SA && TF && TA) // 1111 = 15 { // ALL EXIST: Recursion // Get the New Source and Target Album newSource = getSubAlbum(subName, sourceAlbum); newTarget = getSubAlbum(subName, targetAlbum); // Recursion = Push into Stack CompareStackContent tempStackContent = new CompareStackContent(); tempStackContent.source = newSource; tempStackContent.target = newTarget; recursive.Push(tempStackContent); continue; } else if (SF && SA && !TF && TA) // 1101 = 13 { // TARGET DELETED: Delete Source newSource = getSubAlbum(subName, sourceAlbum); targetAlbum.trim(Album.combinePath(targetAlbum.getPath(), subName), Album.TRIM_ALBUM); resultAlbum[SOURCE_DELETE].add(newSource); continue; } else if (SF && !SA && TF && !TA) // 1010 = 10 { // CREATE ALBUM METADATA: Recursion newSource = new Album(Album.combinePath(sourceAlbum.getPath(), subName)); newTarget = new Album(Album.combinePath(targetAlbum.getPath(), subName)); // ADD TO ALBUM sourceAlbum.add(newSource); targetAlbum.add(newTarget); // Recursion = Push into Stack CompareStackContent tempStackContent = new CompareStackContent(); tempStackContent.source = newSource; tempStackContent.target = newTarget; recursive.Push(tempStackContent); continue; } else if (SF && !SA && !TF && !TA) // 1000 = 8 { try { // NEW JOB: Move Source // POPULATE SA populate(sourceAlbum, Album.combinePath(sourceAlbum.getPath(), subName)); // COPY ALBUM SA -> TA populate(targetAlbum, Album.combinePath(targetAlbum.getPath(), subName), sourceAlbum); newSource = getSubAlbum(subName, sourceAlbum); resultAlbum[SOURCE_LATEST].add(newSource); } catch (UnauthorizedAccessException uae) { // IGNORE: } continue; } else if (!SF && SA && TF && TA) // 0111 = 7 { // DELETE TF newTarget = getSubAlbum(subName, targetAlbum); sourceAlbum.trim(Album.combinePath(sourceAlbum.getPath(), subName), Album.TRIM_ALBUM); resultAlbum[TARGET_DELETE].add(newTarget); continue; } else if (!SF && SA && !TF && TA) // 0101 = 5 { // ERASE ALBUM DATA sourceAlbum.trim(Album.combinePath(sourceAlbum.getPath(), subName), Album.TRIM_ALBUM); targetAlbum.trim(Album.combinePath(targetAlbum.getPath(), subName), Album.TRIM_ALBUM); continue; } else if (!SF && !SA && TF && !TA) // 0010 = 2 { try { // NEW JOB: Move Target // POPULATE TA populate(targetAlbum, Album.combinePath(targetAlbum.getPath(), subName)); // COPY ALBUM TA -> SA populate(sourceAlbum, Album.combinePath(sourceAlbum.getPath(), subName), targetAlbum); newTarget = getSubAlbum(subName, targetAlbum); resultAlbum[TARGET_LATEST].add(newTarget); } catch (UnauthorizedAccessException uae) { // IGNORE: } continue; } else // 0000 = 0 { throw new Exception(INVALID_ALBUM); } } } catch (UnauthorizedAccessException uae) { result.uaeThrown(); } }
/// <summary> /// Public compare function: /// Compare source album with target album and return the difference in an album array /// containing information about the difference of the two albums. /// </summary> /// <param name="sourceAlbum">Source album to be compared (cannot be null).</param> /// <param name="targetAlbum">Target album to be compared (cannot be null).</param> /// <returns> /// Album array containing the difference between the two albums: /// array[0] contains newer files in source album. /// array[1] contains newer files in target album. /// array[2] contains conflict files in source album. /// array[3] contains conflict files in target album. /// array[4] contains deleted files in source album. /// array[5] contains deleted files in target album. /// </returns> public SyncResult compare(Album srcAlbum, Album trgAlbum) { #region Pre Conditions Debug.Assert(srcAlbum != null, "Source Album cannot be null"); Debug.Assert(trgAlbum != null, "Target Album cannot be null"); #endregion #region Initialize Result SyncResult result = new SyncResult(); Album[] resultAlbum = createCompareResultAlbum(); #endregion #region Initialize Stack Stack<CompareStackContent> recursive = new Stack<CompareStackContent>(); CompareStackContent stackContent = new CompareStackContent(srcAlbum, trgAlbum); recursive.Push(stackContent); #endregion Album sourceAlbum, targetAlbum; #region Main Loop do /* Do-While Loop for Performance */ { /* Get the Element Inside Stack */ stackContent = recursive.Pop(); sourceAlbum = stackContent.source; targetAlbum = stackContent.target; /* Files Comparison */ compareFiles(result, resultAlbum, sourceAlbum, targetAlbum); /* Folders Comparison */ compareFolders(result, resultAlbum, recursive, sourceAlbum, targetAlbum); } while (recursive.Count != 0); #endregion // Put the Result Album in Result result.setResult(resultAlbum); #region Post Conditions Debug.Assert(result != null, "Result cannot be null"); #endregion return result; }