Package dnb.analyze.filetree

Source Code of dnb.analyze.filetree.Mp3FileTreeAnalyzer$AlbumDataConfirmInteraction

package dnb.analyze.filetree;

import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;

import dnb.analyze.MatchResult;
import dnb.analyze.SimilarScanResult;
import dnb.analyze.MatchResult.Source;
import dnb.analyze.MatchResult.Status;
import dnb.analyze.SimilarScanResult.Match;
import dnb.analyze.SimilarScanResult.MatchType;
import dnb.analyze.nfo.NfoDataFactory;
import dnb.analyze.nfo.NfoField;
import dnb.analyze.nfo.NfoLyzeResult;
import dnb.analyze.nfo.NfoLyzer;
import dnb.data.Artist;
import dnb.data.CatalogNumber;
import dnb.data.Genre;
import dnb.data.Label;
import dnb.data.Labelcode;
import dnb.data.ReleaseData;
import dnb.data.Repository;
import dnb.data.RepositoryObject;
import dnb.data.filetree.Component;
import dnb.data.filetree.Folder;
import dnb.data.filetree.NfoFile;
import dnb.data.impl.CatalogNumberHibernateImpl;


public class Mp3FileTreeAnalyzer {

  public enum ConfirmResult {
    YES,
    NO,
    IGNORE
  }
  public interface LabelcodeConfirmInteraction
    ConfirmResult confirmLabelcode(Folder f, CatalogNumber code);
  }
 
  public interface AlbumDataConfirmInteraction {
    boolean confirm(NfoFile file, NfoLyzeResult result);
  }
 
  private static final Pattern NUMBER_AT_END_PATTERN = Pattern.compile(".*?(\\d+)$");
  private static final Pattern NFO_LABELCODE_PATTERN = // "Catalog Nr" "CAT.NUMBER" "Catalog"
    Pattern.compile("^.*?cat(?:.*?)(?:nr|no|number)?:?\\s*(.*?)\\s*$",
        Pattern.MULTILINE | Pattern.UNIX_LINES | Pattern.CASE_INSENSITIVE);
 
  // XXX clear out & warn about folders ONLY containing nfos!
 
 
  private static boolean addLabelCode(LabelcodeConfirmInteraction interaction, Set<String> labelCodes, Set<String> ignored,
      Folder cur, CatalogNumberHibernateImpl lc) {
    if(ignored.contains(lc.getCode())) {
      System.out.println("Already ignored:" + lc.getCode());
      return false;
    }
    if (!labelCodes.contains(lc.getCode())) { // new code
      ConfirmResult confirmed = interaction.confirmLabelcode(cur, lc);
      if(confirmed == ConfirmResult.YES) {
        labelCodes.add(lc.getCode());
        cur.setLabelcode(lc); // assign label code to this folder or a parent in the hierarchy
        return true;
      } else if (confirmed == ConfirmResult.IGNORE) {
        ignored.add(lc.getCode());
        return false;
      else {
        return false;
      }     
    } else { // already contained => as good as confirmed
      cur.setLabelcode(lc); // assign label code to this folder or a parent in the hierarchy
      return true;
    }
  }
 
  private static void assignMatchStatus(final MatchResult mr,
      final SimilarScanResult<? extends RepositoryObject> f) {
    if (f == null) { // not found       
      mr.setStatus(MatchResult.Status.UNKNOWN); // better check !
    } else { // one or more matches found...     
      switch(f.getType()) { // check best avail. type
      case LEVENSHTEIN:
      case PART:   
        // IMPORTANT: correct to existing entry NOT with part, but mark both yellow!
        // XXX 4th status for part matches: lookup !!!
        mr.setStatus(MatchResult.Status.SIMILAR); // could be, but better check
        break;
      case EXACT:
        mr.setStatus(MatchResult.Status.KNOWN); // green 2 go ;-)
        if (!mr.getMatch().equals(f.get(0).getFoundObject().getName())) {
          System.out.println("Correcting !");
          mr.setMatch(f.get(0).getFoundObject().getName());
        }       
        break;
      default:
        throw new AssertionError();
      }
    }
  }
 
  // XXX return if part status has been assigned
  private static void assignMatchStati(NfoLyzeResult result, Repository repository) {
   
    Map<NfoField, MatchResult> m = result.getMatches();
    MatchResult mr;
       
    if((mr = m.get(NfoField.ARTIST)) != null) { // get the artist's match result, if set, proceed!     
      SimilarScanResult<Artist> f = repository.findSimilarArtist(mr.getMatch());
      mr.setSimilarScanResult(f); // ... attach similar matches to the match itself     
      assignMatchStatus(mr, f); // ... assign stati
      if (f != null) { // XXX compose alternatives & show on UI !
        System.out.println("*********" + f);
      }
    }
    if((mr = m.get(NfoField.GENRE)) != null) { // get the genre's match result, if set, proceed!     
      SimilarScanResult<Genre> f = repository.findSimilarGenre(mr.getMatch());
      mr.setSimilarScanResult(f); // ... attach similar matches to the match itself 
      assignMatchStatus(mr, f);
      if (f != null) { // XXX compose alternatives & show on UI !
        System.out.println("GENRE: *********" + f);
      }
    }
   
    if((mr = m.get(NfoField.RECORD_LABEL)) != null) { // get the label's match result, if set, proceed!
     
      SimilarScanResult<Label> f = repository.findSimilarLabel(mr.getMatch());
      mr.setSimilarScanResult(f); // ... attach similar matches to the match itself 
      assignMatchStatus(mr, f);
     
      if (f != null) { // XXX compose alternatives & show on UI !
        System.out.println("LABEL: *********" + f);       
      }
    }   
    // most important of all, the cat.no a.k.a. labelcode ;-)
    assignLabelFieldMatchStati(repository, m);
  }

  @SuppressWarnings("unchecked")
  private static boolean checkLabelcodeAgainstLabelAlternatives(MatchResult labelCodeMatch, MatchResult recordLabelMatch) {
    SimilarScanResult<Label> sr = (SimilarScanResult<Label>) recordLabelMatch.getSimilarScanResult();
    if (sr != null) { // 1 - n exact or similar labels found     
      final int ms = sr.size();
      final String lc = labelCodeMatch.getMatch();
      for (int i = 0; i < ms; i++) {  // => check if any of these label objects contains the found code            
         if (sr.get(i).getFoundObject().findLabelcode(lc) != null) {              
           // ... if so, move found label to top (only if it is not no. 1 :-)
           if (i != 0) { sr.setTopMatch(i);
           // => x-reference total success => set both field stati to green
           labelCodeMatch.setStatus(MatchResult.Status.KNOWN);
           recordLabelMatch.setStatus(MatchResult.Status.KNOWN); // changes the similar status to known!!!
           return true; // .. quit & signal success
         }            
      }
      // none of the matching labels contains the code => leave label yellow & set lc to UNKNOWN
      // => nevertheless, x-reference successful
       labelCodeMatch.setStatus(MatchResult.Status.UNKNOWN);
       return true;
    } else { // no label matches => x-reference failed!
      // no matches for the found label name => set labelcode match to UNKNOWN
      labelCodeMatch.setStatus(MatchResult.Status.UNKNOWN);   
      return false;
    }   
  }
 
  private static void assignLabelFieldMatchStati(Repository repository,
      Map<NfoField, MatchResult> matches) {
    MatchResult lcmatch;
    MatchResult labelmatch = matches.get(NfoField.RECORD_LABEL);
   
    if((lcmatch = matches.get(NfoField.LABEL_CODE)) != null) { // get the lc's match result, if set, proceed!
      // we found a label code, if a label name was also found, cross-reference!       
      if (labelmatch !=  null) { // label name parsed successfully
        // try find matching label from label object alternatives, if any
        checkLabelcodeAgainstLabelAlternatives(lcmatch, labelmatch);
      } else { // no label name could be parsed => global-lookup label name from code!
        findLabelByLabelcode(repository, lcmatch, matches);       
      }
    } else { // mr is null => label-code parsing failed - but if...
      if (labelmatch !=  null) { // the label name was parsed successfully, get code alternatives from label objects
        createLabelcodeMatchFromLabel(matches, labelmatch);       
      } // else {} mr = mlbl = null => neither label nor code successfully parsed => no status 2 set => folder analyzer & ID3TagAnalyzer have 2 kick in 2 find it out!
    }
  }

  @SuppressWarnings("unchecked")
  private static void createLabelcodeMatchFromLabel(
      Map<NfoField, MatchResult> matches, MatchResult labelNameMatch) {
    SimilarScanResult<Label> sr = (SimilarScanResult<Label>) labelNameMatch.getSimilarScanResult();
    if (sr != null) { // at least one found label
      Label l = null; // holds the found label
      Labelcode lc;
      SimilarScanResult<Labelcode> srlc = null; // holds the label code alternatives
      Match<Labelcode> mt = null; // holds the virtual match
      // => create virtual label code match from best label match having codes
      final int c = sr.size();
      MatchResult mr = null;
     
      for (int i = 0; i < c; i++) { // iterate label matches
        l = sr.get(i).getFoundObject(); // get label object from match
        if (l.size() == 0) { continue; } // label has no codes => skip
        // label has codes => create matches
        int ci = 0;
        if (mr == null) { // no match result yet => create from best entry & store
          mr = new MatchResult(l.get(ci++).getName(), Source.LOOKUP, Status.SIMILAR); // XXX derived, (not similar) entry ! 
          matches.put(NfoField.LABEL_CODE, mr);
        }
        for (int y = ci; y < l.size(); y++) { // => add other codes as alternatives
          lc = l.get(y);
          // XXX for now, use fake leven, but create virtual match type l8a on
          mt = new Match<Labelcode>(MatchType.LEVENSHTEIN, lc.getName(), lc);
          if (srlc == null) {
            srlc = new SimilarScanResult<Labelcode>(mt);
            mr.setSimilarScanResult(srlc);
          } else { srlc.add(mt); }
        }
      }
     
    } // else {} // no label object matches found, but labelname matched => leave unknown
  }

  private static void findLabelByLabelcode(Repository labelLookup,
      MatchResult labelCodeMatch, Map<NfoField, MatchResult> matchStore) {
   
    String lc = labelCodeMatch.getMatch();
    MatchResult mlbl;
    Label other = labelLookup.findByLabelcode(lc);
    if (other != null) { // we got a label name for our code
      // => create virtual label name match!
      mlbl = new MatchResult(other.getName(), Source.LOOKUP, Status.KNOWN);
      mlbl.setSimilarScanResult(new SimilarScanResult<Label>(
          new Match<Label>(MatchType.EXACT, other.getName(), other)));
      matchStore.put(NfoField.RECORD_LABEL, mlbl);
      // set label code match to green & create EXACT scan result
      labelCodeMatch.setStatus(Status.KNOWN);
      Labelcode found = other.findLabelcode(lc); // refind to get the lc object
      labelCodeMatch.setSimilarScanResult(new SimilarScanResult<Labelcode>(
          new Match<Labelcode>(MatchType.EXACT, found.getName(), found)));
    } else { // no label name could be parsed AND no label found for our code
      labelCodeMatch.setStatus(MatchResult.Status.UNKNOWN); // => set to unknown, too
    }
  }

 
  public static void analyzeFolders(Repository repository, List<Folder> list, AlbumDataConfirmInteraction confirmInteraction) {
    int s;
    Component c;
    NfoLyzer nfoLyzer = new NfoLyzer();
       
    for (Folder f : list) { // for all folders,
      s = f.size();
     
      NfoLyzeResult result = new NfoLyzeResult(f); // one nfo result per folder... 
     
      for (int i = 0; i < s; i++) { // iterate files,
        c = f.get(i);
        if (c instanceof NfoFile) { // find nfos
          try {
            if (!nfoLyzer.parseNfo(result, (NfoFile) c)) {
              System.out.println("No parser for " + c.pathString() + ", trying next nfo.");             
              continue;             
            } else {
              // parse success => validate, create & save album data
              // set repository object candidates and the status of all index fields
              assignMatchStati(result, repository); // find known or similar entries & set stati accordingly
              // some post-processing
              postProcess(result);
              if(confirmInteraction.confirm((NfoFile) c, result)) {
                // confirmed => convert to Album data & persist!
                ReleaseData d = NfoDataFactory.fromNfo(result, repository);
                System.out.println(d);
              } else {
                System.out.println("DECLINED!");               
              }
              break; // cancel nfo discovery
             
            }
          }catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          } catch(RuntimeException e) {
            System.out.println(e.getMessage());
          }
        }
      }
      if (result.getMatches().isEmpty()) {
        System.out.println("Folder parser required for " + f.pathString());
      }
    }
  }

  // XXX: => to postprocessor!
  private static void postProcess(NfoLyzeResult result) {
    // rule 1: known label code = title => set title known
    MatchResult lc = result.getMatches().get(NfoField.LABEL_CODE);
    MatchResult t = result.getMatches().get(NfoField.ALBUM_TITLE);                           
    if(lc != null && t != null // got both title & a known lc
      && lc.getStatus() == Status.KNOWN
      && lc.getMatch().equalsIgnoreCase(t.getMatch())) {     
      t.setStatus(Status.KNOWN);
    }
   
    // rule 2: label name contains a numeric that NfoField.LABEL_CODE_NO starts with => parsing probably failed!
    MatchResult ln = result.getMatches().get(NfoField.RECORD_LABEL);
    MatchResult lcn = result.getMatches().get(NfoField.LABEL_CODE_NO);
   
    if (ln != null && lcn != null) {
      Matcher m = NUMBER_AT_END_PATTERN.matcher(ln.getMatch());     
      String no = lcn.getMatch();     
      if (m.find()) {
        String mt = m.group(1);
        if (no.startsWith(mt)) {
          lcn.setMatch(no.substring(mt.length()));
          lcn.setStart(lcn.getStart() + 2);
          lc.setMatch(lc.getMatch() + mt);
          lc.setEnd(lc.getEnd() + 2);
          System.err.println("!!!!!!!ERROR!!!!!!!!!!!!!!!!");
          // XXX: => visualize this critital error & its correction on the ui
        }       
      }
    }
   

  }
 
  public static void assignLabelcodes(LabelcodeConfirmInteraction interaction, List<Folder> list, Set<String> labelCodes,
      Set<String> ignored, boolean folderNameIsLabelcode, boolean lookupLabelcodeInNfo) {
    for (Folder f : list) {
      if (f.findLabelcode() == null) { // no label code for this folder yet => assign
        CatalogNumberHibernateImpl lc = null;
        // walk bottom up and try to find label code
        Folder cur = f;
        if (folderNameIsLabelcode) {
          while(cur.getParent().getName() != null) { // walk until root
            lc = LabelcodeMatcher.findLabelcode(cur.getName());
            if (lc == null) {
              lc = LabelcodeMatcher.findLabelcode2(cur.getName());
            }
            if (lc != null) {
              break;
            }
            cur = (Folder) cur.getParent();
          }
        } else {
          while(cur.getParent().getName() != null // walk until root
              && (lc = LabelcodeMatcher.findLabelcode(cur.getName())) == null) {
            cur = (Folder) cur.getParent();
          }
        }       
        if (lc != null) { // got label code from folder => confirm
          if(!addLabelCode(interaction, labelCodes, ignored, cur, lc)) {
            // not confirmed => try get from nfo if indicated
            if (lookupLabelcodeInNfo) {
              lc = fromNfo(f);
              if (lc != null) {
                // try 2 get this label code confirmed
                addLabelCode(interaction, labelCodes, ignored, f, lc);
              }
            }
          } 
        } else if (lookupLabelcodeInNfo) {
          lc = fromNfo(f);
          if (lc != null) {
            // try 2 get this label code confirmed
            addLabelCode(interaction, labelCodes, ignored, f, lc);
          }         
        }         
      }
    }
  }
 
  private static CatalogNumberHibernateImpl fromNfo(Folder f) {
   
    final int s = f.size();
    Component c;
    CatalogNumberHibernateImpl lc = null;
    String lm = null;
    for (int i = 0; i < s; i++) {
      c = f.get(i);
      if (c instanceof NfoFile) {
        String pth = c.pathString();
        try {
          System.out.println("Processing " + pth);
          String nfo = IOUtils.toString(new FileReader(pth));
          Matcher m = NFO_LABELCODE_PATTERN.matcher(nfo);
         
          while (m.find()) {
            lc = LabelcodeMatcher.findLabelcode(m.group(1));
            lm = m.group();
            if (lc == null) { // try less strict
              lc = LabelcodeMatcher.findLabelcode2(m.group(1));
            }           
            if (lc != null) { // found => quit looking @ current nfo
              break;
            }
          }
                   
          if (lc != null) { // found => quit looking @ other nfos
            break;
          }
        } catch (IOException e) {
          System.err.println("Unable to open " + pth);
        }
      }     
    }
    if (lm != null)  {
      System.out.println(lm);
    }
   
    return lc;
  }
}
TOP

Related Classes of dnb.analyze.filetree.Mp3FileTreeAnalyzer$AlbumDataConfirmInteraction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.