package org.farng.mp3.filename; import java.util.Iterator; import org.farng.mp3.AbstractMP3Tag; import org.farng.mp3.TagOptionSingleton; import org.farng.mp3.id3.AbstractFrameBodyTextInformation; import org.farng.mp3.id3.AbstractFrameBodyUrlLink; import org.farng.mp3.id3.AbstractID3v2Frame; import org.farng.mp3.id3.AbstractID3v2FrameBody; import org.farng.mp3.id3.FrameBodyCOMM; import org.farng.mp3.id3.ID3v2_4; import org.farng.mp3.id3.ID3v2_4Frame; /** * This composite subclass is the leaf of the tree. It contains the actual strings found in the filename. * * @author Eric Farng * @version $Revision: 2374 $ */ public class FilenameToken extends AbstractFilenameComposite { /** * what information this object represents. */ private Class id3v2FrameBodyClass = null; /** * token that this object represents */ private String token = null; /** * Creates a new FilenameToken object. */ public FilenameToken() { super(); } /** * Creates a new FilenameToken object. */ public FilenameToken(final FilenameToken copyObject) { super(copyObject); try { id3v2FrameBodyClass = id3v2FrameBodyClass.newInstance().getClass(); } catch (IllegalAccessException ex) { throw new NullPointerException("IllegalAccessException: No access to run constructor to create copy " + ex.getMessage()); } catch (InstantiationException ex) { throw new NullPointerException("InstantiationException: Unable to instantiate constructor to copy " + ex.getMessage()); } token = copyObject.token; } public void setFrame(final AbstractID3v2Frame frame) { if (id3v2FrameBodyClass != null && id3v2FrameBodyClass.equals(frame.getBody().getClass())) { //todo add support for more tag matches. only doing text // information and URL links right now because i'm lazy if (AbstractFrameBodyTextInformation.class.isInstance(frame.getBody())) { token = ((AbstractFrameBodyTextInformation) frame.getBody()).getText(); } else if (AbstractFrameBodyUrlLink.class.isInstance(frame.getBody())) { token = ((AbstractFrameBodyUrlLink) frame.getBody()).getUrlLink(); } } } /** * Sets the ID3v2 frame body that this token represents * * @param id3v2FrameBodyClass the ID3v2 frame body that this token represents */ public void setId3v2FrameBodyClass(final Class id3v2FrameBodyClass) { this.id3v2FrameBodyClass = id3v2FrameBodyClass; } /** * Returns the ID3v2 frame body that this token represents * * @return the ID3v2 frame body that this token represents */ public Class getId3v2FrameBodyClass() { return id3v2FrameBodyClass; } /** * Sets the token that this class contains * * @param token the token that this class contains */ public void setToken(final String token) { this.token = token.trim(); } /** * Return the token that this class contains * * @return the token that this class contains */ public String getToken() { return token; } /** * Reconstruct the filename that is represented by this composite. * * @return the filename that is represented by this composite. */ public String composeFilename() { return token; } public ID3v2_4 createId3Tag() { final ID3v2_4 newTag = new ID3v2_4(); if (id3v2FrameBodyClass != null) { try { final AbstractID3v2FrameBody body = (AbstractID3v2FrameBody) id3v2FrameBodyClass.newInstance(); //todo need to add support for more frame bodies here if (body instanceof AbstractFrameBodyTextInformation) { ((AbstractFrameBodyTextInformation) body).setText(token); ((AbstractFrameBodyTextInformation) body).setTextEncoding((byte) 0); } else if (body instanceof AbstractFrameBodyUrlLink) { ((AbstractFrameBodyUrlLink) body).setUrlLink(token); } else if (body instanceof FrameBodyCOMM) { ((FrameBodyCOMM) body).setText(token); ((FrameBodyCOMM) body).setDescription(""); ((FrameBodyCOMM) body).setLanguage(TagOptionSingleton.getInstance().getLanguage()); ((FrameBodyCOMM) body).setTextEncoding(TagOptionSingleton.getInstance().getTextEncoding()); } final ID3v2_4Frame frame = new ID3v2_4Frame(); frame.setBody(body); newTag.setFrame(frame); } catch (IllegalAccessException ex) { // catch and dont' create the frame } catch (InstantiationException ex) { // catch and dont' create the frame } } return newTag; } /** * Returns an iterator through each <code>FilenameToken</code> in this composite in the correct order for the file * name. * * @return an iterator through each <code>FilenameToken</code> in this composite */ public Iterator iterator() { return new FilenameTokenIterator(this); } /** * Match all elements of this composite against the keywords for this class type found in * <code>TagOptionSingleton</code>. If the <code>FilenameToken</code> matches the keyword, the token's class is * set. * * @param matchId3v2FrameBodyClass Class of keywords to match against. */ public void matchAgainstKeyword(final Class matchId3v2FrameBodyClass) { if (AbstractID3v2FrameBody.class.isAssignableFrom(matchId3v2FrameBodyClass)) { if (TagOptionSingleton.getInstance().isCompositeMatchOverwrite() || id3v2FrameBodyClass == null) { final Iterator iterator = TagOptionSingleton.getInstance() .getKeywordListIterator(matchId3v2FrameBodyClass); final String lowerCaseToken = token.toLowerCase(); while (iterator.hasNext()) { final String matchString = ((String) iterator.next()).toLowerCase(); if (matchString.equals(lowerCaseToken) || matchString.indexOf(lowerCaseToken) >= 0 || lowerCaseToken.indexOf(matchString) >= 0) { setId3v2FrameBodyClass(matchId3v2FrameBodyClass); break; } } } } } /** * Match all elements of this composite against the given tag. If any element of <code>matchTag</code> matches any * element of this tag's composite, then this tag's composite leaf node's class is set. * * @param matchTag Tag to match against */ public void matchAgainstTag(final AbstractMP3Tag matchTag) { if (TagOptionSingleton.getInstance().isCompositeMatchOverwrite() || id3v2FrameBodyClass == null) { final ID3v2_4 tag; if (matchTag instanceof ID3v2_4) { tag = (ID3v2_4) matchTag; } else { tag = new ID3v2_4(matchTag); } final Iterator iterator = tag.iterator(); AbstractID3v2Frame frame; AbstractID3v2FrameBody body; String matchString = null; final String lowerCaseToken = token.toLowerCase(); while (iterator.hasNext()) { frame = (ID3v2_4Frame) iterator.next(); body = (AbstractID3v2FrameBody) frame.getBody(); //todo add support for more tag matches. only doing text // information and URL links right now because i'm lazy if (body instanceof AbstractFrameBodyTextInformation) { matchString = ((AbstractFrameBodyTextInformation) body).getText(); if (matchString != null) { matchString = matchString.toLowerCase(); } } else if (body instanceof AbstractFrameBodyUrlLink) { matchString = ((AbstractFrameBodyUrlLink) body).getUrlLink(); if (matchString != null) { matchString = matchString.toLowerCase(); } } else if (body instanceof FrameBodyCOMM) { matchString = ((FrameBodyCOMM) body).getText(); } if (lowerCaseToken.equals(matchString) || matchString != null && (matchString.indexOf(lowerCaseToken) >= 0 || lowerCaseToken.indexOf(matchString) >= 0)) { setId3v2FrameBodyClass(body.getClass()); break; } } } } /** * Returns a string containing debug information about this class * * @return a string containing debug information about this class */ public String toString() { return id3v2FrameBodyClass + ": " + token; } }