package model;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import model.regex.Regex;
public class ID3TagRegex {
/**
* the logger
*/
private final Logger logger = Logger.getLogger(this.getClass().getName());
/*
* component shorts
*/
public static final String TITLE = "%t";
public static final String ARTIST = "%a";
public static final String ALBUMARTIST = "%b";
public static final String ALBUM = "%z";
public static final String YEAR = "%y";
public static final String TRACK = "%n";
public static final String MAXTRACKS = "%l";
public static final String CD = "%c";
public static final String MAXCD = "%x";
public static final String GENRE = "%g";
public static final String COMMENT = "%q";
public static final String PUBLISHER = "%p";
public static final String COMPOSER = "%s";
public static final String ORIGARTIST = "%o";
public static final String COPYRIGHT = "%r";
public static final String URL = "%u";
public static final String ENCODEDBY = "%e";
/**
* given source regex
*/
private String src;
/**
* given target regx
*/
private String target;
/**
* the regex string which is generated from the source to match each file
* e.g. (.*?)-(.*?)
*/
private String regexString;
/**
* the regex object
*/
private Regex regex;
/**
* maps the index to the corresponding short e.g. %t-%n-%a would be 1:=%t,
* 2:=%n, 3:=%a
*/
private Map<Integer, String> groupIndex;
/**
* array which represents if the generated regex contains the short e.g.
* index 0 = 1 means the Title is included
*/
private boolean[] containsTags;
/**
* Constructor
*
* @param regex
* given regex string
*/
public ID3TagRegex(String regex) {
this.src = regex;
this.target = "";
this.groupIndex = new HashMap<Integer, String>();
findGroupIndex();
generateRegex();
generateContainedTags();
}
/**
* Constructor
*
* @param src
* given source regex
* @param target
* given target regex
*/
public ID3TagRegex(String src, String target) {
this.src = src;
this.target = target;
this.groupIndex = new HashMap<Integer, String>();
findGroupIndex();
generateRegex();
generateContainedTags();
}
/**
* finds the group index for every shortcut e.g. %t-%n-%a would be 1:=%t,
* 2:=%n, 3:=%a
*/
private void findGroupIndex() {
int index = 1;
for (int i = 0; i < src.length(); i++) {
// found %
if (src.charAt(i) == '%') {
// check if there is one more char
if (i < src.length() - 1) {
// check if sequence is valid
if (isValid(src.charAt(i + 1))) {
logger.log(Level.FINER, "found groupindex: " + index + " with %" + src.charAt(i + 1));
this.groupIndex.put(index, "%" + src.charAt(i + 1));
index++;
}
}
}
}
}
/**
* generated the containsTag array
*/
private void generateContainedTags() {
this.containsTags = new boolean[] { containsTag(ID3TagRegex.TITLE), containsTag(ID3TagRegex.ARTIST), containsTag(ID3TagRegex.ALBUMARTIST), containsTag(ID3TagRegex.ALBUM),
containsTag(ID3TagRegex.YEAR), containsTag(ID3TagRegex.TRACK), containsTag(ID3TagRegex.MAXTRACKS), containsTag(ID3TagRegex.CD), containsTag(ID3TagRegex.MAXCD),
containsTag(ID3TagRegex.GENRE), containsTag(ID3TagRegex.COMMENT), containsTag(ID3TagRegex.COMPOSER), containsTag(ID3TagRegex.ORIGARTIST),
containsTag(ID3TagRegex.COPYRIGHT), containsTag(ID3TagRegex.URL), containsTag(ID3TagRegex.ENCODEDBY) };
}
/**
* true if the given tag is in the regex, else false
*
* @param tag
* the tag to check
*
* @return true or false
*/
private boolean containsTag(String tag) {
for (String t : this.groupIndex.values())
if (t.equals(tag))
return true;
return false;
}
/**
* generates a regex from the src String and escapes all regex characters
* e.g. %t-%n-%a would be (.*?)-(.*?)-(.*?)
*/
private void generateRegex() {
this.regexString = src;
Regex.replaceRegexChars(this.regexString);
this.regexString = this.regexString.replace(TITLE, "(.*?)");
this.regexString = this.regexString.replace(ARTIST, "(.*?)");
this.regexString = this.regexString.replace(ALBUMARTIST, "(.*?)");
this.regexString = this.regexString.replace(ALBUM, "(.*?)");
this.regexString = this.regexString.replace(YEAR, "(.*?)");
this.regexString = this.regexString.replace(TRACK, "(.*?)");
this.regexString = this.regexString.replace(MAXTRACKS, "(.*?)");
this.regexString = this.regexString.replace(CD, "(.*?)");
this.regexString = this.regexString.replace(MAXCD, "(.*?)");
this.regexString = this.regexString.replace(GENRE, "(.*?)");
this.regexString = this.regexString.replace(COMMENT, "(.*?)");
this.regexString = this.regexString.replace(PUBLISHER, "(.*?)");
this.regexString = this.regexString.replace(COMPOSER, "(.*?)");
this.regexString = this.regexString.replace(ORIGARTIST, "(.*?)");
this.regexString = this.regexString.replace(COPYRIGHT, "(.*?)");
this.regexString = this.regexString.replace(URL, "(.*?)");
this.regexString = this.regexString.replace(ENCODEDBY, "(.*?)");
logger.log(Level.FINER, "new Regex string is: " + this.regex);
this.regex = new Regex(this.regexString, Pattern.CASE_INSENSITIVE);
}
/**
* checks if %Char is valid
*
* @param c
* given Char
*
* @return true if valid, else false
*/
private boolean isValid(char c) {
switch (c) {
case 't':
return true;
case 'a':
return true;
case 'b':
return true;
case 'z':
return true;
case 'y':
return true;
case 'n':
return true;
case 'l':
return true;
case 'c':
return true;
case 'x':
return true;
case 'g':
return true;
case 'q':
return true;
case 'p':
return true;
case 's':
return true;
case 'o':
return true;
case 'r':
return true;
case 'u':
return true;
case 'e':
return true;
}
return false;
}
/**
* modifies the given name e.g. %t-%n-%a to %a-%n-%t from "Track-Nr-Artist"
* would return "Artist-Nr-Track"
*
* @param name
* given name of the file
*
* @return the new name depending on the given src and target
*/
public String modifyString(String name) {
logger.log(Level.FINER, "modify String: " + name + " match: " + this.regex.matches(name));
if (!this.regex.matches(name))
return name;
String result = target;
for (Integer i : this.groupIndex.keySet()) {
result = result.replace(this.groupIndex.get(i), this.regex.getGroup(i));
}
return result;
}
/**
* gets the given value for of the given name depending on the given regex
*
* @param tag
* given tag (can be found as attributes in ID3TagRegex)
* @param name
* given filename
*
* @return the value, or null if it doesnt exist
*/
public String getTag(String tag, String name) {
int index = getAttributIndex(tag);
if (index == -1)
return "";
if (regex.matches(name))
return regex.getGroup(index).trim();
return "";
}
/**
* gets the index for the given tag
*
* @param tag
* given tag
*
* @return the index for the saved regex. -1 if the tag doesn't exists
*/
private int getAttributIndex(String tag) {
for (int index : this.groupIndex.keySet()) {
if (tag.equals(this.groupIndex.get(index)))
return index;
}
return -1;
}
/**
* gets the containsTag array
*
* @return the array
*/
public boolean[] getContainsTags() {
return containsTags;
}
}