package model.collector.lastfm; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import model.collector.Album; import model.collector.Track; import model.regex.Regex; public class XMLAlbumParser { /** * the logger */ private final Logger logger = Logger.getLogger(this.getClass().getName()); /** * the album */ private Album album; // regex for dd www yyyy, dd:dd --> gets year /** * the year regex */ private static Regex yearRegex = new Regex(".+ .+ (\\d+), .*", Pattern.CASE_INSENSITIVE); /** * gets the album * * @return the album */ public Album getAlbum() { return this.album; } /** * Constructor * * @param url * url where the xml code can be found * * @throws MalformedURLException * @throws XMLStreamException * @throws IOException */ public XMLAlbumParser(String url) throws MalformedURLException, XMLStreamException, IOException { logger.log(Level.FINER, "parse Album xml. URL: " + url); album = new Album(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLStreamReader parser = factory.createXMLStreamReader(new URL(url).openStream()); extractAlbum(parser); } /** * extracts the album * * @param parser * the parser * * @throws XMLStreamException */ private void extractAlbum(XMLStreamReader parser) throws XMLStreamException { while (parser.hasNext()) { switch (parser.getEventType()) { case XMLStreamConstants.START_ELEMENT: { // check status first if (parser.getLocalName().equalsIgnoreCase("lfm")) { String status = "failed"; if (parser.getAttributeCount() > 0) status = parser.getAttributeValue(0); if (!status.equalsIgnoreCase("ok")) return; } else if (parser.getLocalName().equalsIgnoreCase("name")) { parser.next(); if (parser.getEventType() == XMLStreamConstants.CHARACTERS) this.album.setName(parser.getText()); logger.log(Level.FINER, "extract album name: " + this.album.getName()); } else if (parser.getLocalName().equalsIgnoreCase("artist")) { parser.next(); if (parser.getEventType() == XMLStreamConstants.CHARACTERS) this.album.setArtist(parser.getText()); logger.log(Level.FINER, "extract artist name: " + this.album.getArtist()); } else if (parser.getLocalName().equalsIgnoreCase("releasedate")) { parser.next(); if (parser.getEventType() == XMLStreamConstants.CHARACTERS) this.album.setYear(parseYear(parser.getText())); logger.log(Level.FINER, "extract year: " + this.album.getYear()); } else if (parser.getLocalName().equalsIgnoreCase("image")) { if (parser.getAttributeCount() > 0) this.album.setImageSize(parser.getAttributeValue(0)); parser.next(); if (parser.getEventType() == XMLStreamConstants.CHARACTERS) this.album.setImageURL(parser.getText()); logger.log(Level.FINER, "extract image url: " + this.album.getImageURL() + " with size: " + this.album.getImageSize()); } else if (parser.getLocalName().equalsIgnoreCase("track")) { extractTrack(parser); } else if (parser.getLocalName().equalsIgnoreCase("tag")) { extractTags(parser); } break; } case XMLStreamConstants.END_ELEMENT: { break; } case XMLStreamConstants.END_DOCUMENT: { logger.log(Level.FINER, "Document finished"); parser.close(); return; } } parser.next(); } } /** * extracts the tracks * * @param parser * the parser * * @throws XMLStreamException */ private void extractTrack(XMLStreamReader parser) throws XMLStreamException { Track track = new Track(); logger.log(Level.FINER, "create new Track."); while (parser.hasNext()) { switch (parser.getEventType()) { case XMLStreamConstants.START_ELEMENT: { if (parser.getLocalName().equalsIgnoreCase("track")) { if (parser.getAttributeCount() > 0) track.setTrackNr(Integer.parseInt(parser.getAttributeValue(0))); logger.log(Level.FINER, "Track#: " + track.getTrackNr()); } else if (parser.getLocalName().equalsIgnoreCase("name")) { parser.next(); track.setTitle(parser.getText()); logger.log(Level.FINER, "Track title: " + track.getTitle()); } else if (parser.getLocalName().equalsIgnoreCase("artist")) { parser.next(); parser.next(); parser.next(); if (parser.getEventType() == XMLStreamConstants.CHARACTERS) track.setArtist(parser.getText()); logger.log(Level.FINER, "Track artist: " + track.getArtist()); } break; } case XMLStreamConstants.END_ELEMENT: { if (parser.getLocalName().equalsIgnoreCase("track")) { logger.log(Level.FINER, "adding Track"); this.album.addTrack(track); return; } break; } } parser.next(); } } /** * extracts the tags * * @param parser * the parser * * @throws XMLStreamException */ private void extractTags(XMLStreamReader parser) throws XMLStreamException { while (parser.hasNext()) { switch (parser.getEventType()) { case XMLStreamConstants.START_ELEMENT: { if (parser.getLocalName().equalsIgnoreCase("name")) { parser.next(); String tag = ""; if (parser.getEventType() == XMLStreamConstants.CHARACTERS) { tag = parser.getText(); this.album.addTag(tag); } logger.log(Level.FINER, "added Tag: " + tag); } break; } case XMLStreamConstants.END_ELEMENT: { if (parser.getLocalName().equalsIgnoreCase("tag")) { return; } break; } } parser.next(); } } /** * parses the year using the defined rege * * @param date * the date * * @return the year as a string */ private String parseYear(String date) { if (yearRegex.matches(date)) return yearRegex.getGroup(1); return ""; } }