001/* 002 * $URL: svn://svn.webarts.bc.ca/open/trunk/projects/WebARTS/ca/bc/webarts/tools/MusicBrainzRestRequester.java $ 003 * $Author: tgutwin $ 004 * $Revision: 1219 $ 005 * $Date: 2018-03-02 22:12:45 -0800 (Fri, 02 Mar 2018) $ 006 */ 007/* 008 * 009 * Written by Tom Gutwin - WebARTS Design. 010 * Copyright (C) 2014-2016 WebARTS Design, North Vancouver Canada 011 * http://www.webarts.ca 012 * 013 * This program is free software; you can redistribute it and/or modify 014 * it under the terms of the GNU General Public License as published by 015 * the Free Software Foundation; version 3 of the License, or 016 * (at your option) any later version. 017 * 018 * This program is distributed in the hope that it will be useful, 019 * but WITHOUT ANY WARRANTY; without_ even the implied warranty of 020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 021 * GNU General Public License for more details. 022 * 023 * You should have received a copy of the GNU General Public License 024 * along with this program; if not, write to the Free Software 025 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 026 */ 027 028package ca.bc.webarts.tools; 029 030import java.io.IOException; 031import java.io.File; 032import java.io.FileNotFoundException; 033import java.lang.Integer; 034import java.net.HttpURLConnection; 035import java.net.MalformedURLException; 036import java.net.URL; 037import java.net.URLEncoder; 038import java.util.Arrays; 039import java.util.Comparator; 040import java.util.Hashtable; 041import java.util.Set; 042import java.util.Vector; 043 044 045import ca.bc.webarts.tools.RestRequester; 046import ca.bc.webarts.widgets.Util; 047import ca.bc.webarts.widgets.Quick; 048 049import org.apache.commons.codec.binary.Base64; 050 051import nu.xom.Attribute; 052import nu.xom.Builder; 053import nu.xom.Document; 054import nu.xom.Element; 055import nu.xom.Elements; 056import nu.xom.Node; 057import nu.xom.ParsingException; 058import nu.xom.ValidityException; 059import nu.xom.Serializer; 060import nu.xom.XPathException; 061 062 063/** 064 * This class wraps the communication to the REST interface to MusicBrainz. 065 * The web service root URL is https://musicbrainz.org/ws/2/ 066 * We have 12 resources on our web service which represent core entities in our database: 067 * area, artist, event, instrument, label, place, recording, release, release-group, series, work, url 068 * We also provide a web service interface for the following non-core resources: 069 * rating, tag, collection 070 * And we allow you to perform lookups based on other unique identifiers with these resources: 071 * <code>discid, isrc, iswc</code><ul> 072 * On each entity resource, you can perform three different GET requests: 073 * 074 * <li>lookup: /<ENTITY>/<MBID>?inc=<INC></li> 075 * <li>browse: /<ENTITY>?<ENTITY>=<MBID>&limit=<LIMIT>&offset=<OFFSET>&inc=<INC></li> 076 * <li>search: /<ENTITY>?query=<QUERY>&limit=<LIMIT>&offset=<OFFSET></li> 077 * ... except that search is not implemented for URL entities at this time.</ul><br /> 078 * 079 * Written by Tom Gutwin - WebARTS Design.<br /> 080 * Copyright © 2018 WebARTS Design, North Vancouver Canada<br /> 081 * <a href="http://www.webarts.ca">http://www.webarts.ca</a> 082 * 083 * @author Tom B. Gutwin 084 **/ 085public class MusicBrainzRestRequester extends RestRequester 086{ 087 protected static final String CLASSNAME = "ca.bc.webarts.tools.MusicBrainzRestRequester"; //ca.bc.webarts.widgets.Util.getCurrentClassName(); 088 public static final String LOG_TAG = "\n"+CLASSNAME; //+"."+ca.bc.webarts.android.Util.getCurrentClassName(); 089 090 /** DEFAULT MUSICBRAINZ IP address to use: 10.0.0.207 .**/ 091 protected static final String DEFAULT_MUSICBRAINZ_IP = "musicbrainz.org"; 092 /** DEFAULT MUSICBRAINZ username to use: admin .**/ 093 protected static final String DEFAULT_MUSICBRAINZ_USERNAME = "admin"; 094 /** DEFAULT MUSICBRAINZ password to use: admin .**/ 095 protected static final String DEFAULT_MUSICBRAINZ_PASSWORD = "admin"; 096 /** DEFAULT MUSICBRAINZ rest URL to start the URL path: /rest .**/ 097 protected static final String DEFAULT_MUSICBRAINZ_REST_URL_PATHSTR = "/ws/2"; 098 /** A default Release MRID to use for testing. Barenaked Ladies, Gordon. **/ 099 protected static final String DEFAULT_MUSICBRAINZ_TEST_RELEASE_MRID = "38e73fee-7420-4f3a-805a-6fdfac011ac2"; 100 protected static final String DEFAULT_MUSICBRAINZ_TEST_ARTIST_MRID = "86e736b4-93e2-40ff-9e1c-fb7c63fef5f6"; 101 102 103 protected static StringBuilder helpMsg_ = new StringBuilder(SYSTEM_LINE_SEPERATOR); 104 protected static boolean debugOut_ = false; 105 protected static boolean doWrites_ = true; 106 107 protected String metaDataFilename_ = "mbData.props"; 108 109 /** The start path to use in therest URL. Over-ride this if you extend this class. **/ 110 protected String restUrlPath_ = DEFAULT_MUSICBRAINZ_REST_URL_PATHSTR; 111 Builder xmlBuilder_ = new Builder(); 112 113 /** 114 * Default constructor . 115 * 116 * @see #DEFAULT_MUSICBRAINZ_IP 117 * @see #DEFAULT_MUSICBRAINZ_USERNAME 118 * @see #DEFAULT_MUSICBRAINZ_PASSWORD 119 **/ 120 public MusicBrainzRestRequester() 121 { 122 authenticating_=false; 123 setBaseUrl( "https://"+DEFAULT_MUSICBRAINZ_IP+restUrlPath_); 124 setUsername( DEFAULT_MUSICBRAINZ_USERNAME); 125 setPassword( DEFAULT_MUSICBRAINZ_PASSWORD); 126 } 127 128 129 /** 130 * Constructor to customize all connection settings. 131 * 132 **/ 133 public MusicBrainzRestRequester(String server, String user, String pass) 134 { 135 setBaseUrl( "https://"+server+restUrlPath_); 136 authenticating_=true; 137 setUsername(user); 138 setPassword( pass); 139 } 140 141 /** 142 * Set Method for class field 'restUrlPath_'. 143 * 144 * @param restUrlPath_ is the value to set this class field to. 145 * 146 **/ 147 public void setRestUrlPath(String restUrlPath) 148 { 149 restUrlPath_ = restUrlPath; 150 } // setRestUrlPath Method 151 152 153 /** 154 * Get Method for class field 'restUrlPath_'. 155 * 156 * @return String - The value the class field 'restUrlPath_'. 157 * 158 **/ 159 public String getRestUrlPath() 160 { 161 return restUrlPath_; 162 } // getRestUrlPath Method 163 164 165 /** Check connectivity to the MusicBrainz URL specified by the class parms. 166 * @return true or false 167 **/ 168 public boolean canConnect() 169 { 170 if(debugOut_) System.out.println(LOG_TAG+".canConnect("+getBaseUrl()+", "+getUsername()+", "+getPassword()+")"); 171 172 boolean retVal = false; 173 if(isInit()) 174 { 175 try 176 { 177 if(debugOut_) System.out.println(LOG_TAG+".init = true"); 178 String usrlStr = (baseUrl_+"/release/"+DEFAULT_MUSICBRAINZ_TEST_RELEASE_MRID).replace(" " ,"%20"); 179 URL url = new URL(usrlStr); 180 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 181 conn.setRequestMethod("GET"); 182 if(acceptJSON_) 183 conn.setRequestProperty("Accept", "application/json"); 184 else 185 conn.setRequestProperty("Accept", "application/xml"); 186 187 conn.setRequestProperty("User-Agent", USER_AGENT+" ( tgutwin@webarts.ca )"); 188 189 if (authenticating_) 190 { 191 //BASE64Encoder enc = new sun.misc.BASE64Encoder(); 192 String userpassword = username_ + ":" + password_; 193 //String encodedAuthorization = android.util.Base64.encodeToString( userpassword.getBytes(), android.util.Base64.DEFAULT ); 194 String encodedAuthorization = new String(Base64.encodeBase64( (userpassword.getBytes()) )); 195 conn.setRequestProperty("Authorization", "Basic "+ encodedAuthorization); 196 } 197 198 if (conn.getResponseCode() == 200) 199 { 200 retVal=true; 201 } // valid http response code 202 conn.disconnect(); 203 } 204 catch (MalformedURLException e) 205 { 206 e.printStackTrace(); 207 } 208 catch (IOException e) 209 { 210 e.printStackTrace(); 211 } 212 } 213 return retVal; 214 } 215 216 217 /** returns the status for all the nodes. **/ 218 public StringBuilder getStatus() 219 { 220 return serviceGet("/status"); 221 } 222 223 224 /** queries all the nodes. **/ 225 public StringBuilder getQuery() 226 { 227 return serviceGet("/query"); 228 } 229 230 231 232 233 /** returns config. **/ 234 public StringBuilder getConfig() 235 { 236 return serviceGet("/config"); 237 } 238 239 240 241 /** 242 * Class main commandLine entry method that has a test command and some convienience commands, as well as a pure rest command. 243 **/ 244 public static void main(String [] args) 245 { 246 final String methodName = CLASSNAME + ": main()"; 247 248 MusicBrainzRestRequester instance = new MusicBrainzRestRequester(); 249 250 /* Simple way af parsing the args */ 251 if (args ==null || args.length<1) 252 System.out.println(getHelpMsgStr()); 253 /* *************************************** */ 254 else 255 { 256 if (args[0].equalsIgnoreCase("test")) 257 { 258 instance.debugOut_=false; 259 260 instance.setAcceptJSON(false); // flase means get XML 261 System.out.println("Can Connect? "+(instance.canConnect()?"Yes":"No")); 262 System.out.println("\n**************************\nLookup Barenaked Ladies - Gordon "); 263 String [] incs = {"artists"}; 264 String releaseResults = instance.lookupRelease(DEFAULT_MUSICBRAINZ_TEST_RELEASE_MRID, incs).toString(); 265 String artistResults = instance.lookupArtist(DEFAULT_MUSICBRAINZ_TEST_ARTIST_MRID).toString(); 266 String searchResults = instance.searchRelease("Barenaked Ladies", "Gordon").toString(); 267 try 268 { 269 System.out.println("\n\n"+"Release\n~~~~~~~~~~~~~~~~"); 270 System.out.println(Util.xmlToPrettyString(releaseResults, 2)); 271 nu.xom.Document releaseDoc = instance.parseXMLResponse(releaseResults); 272 System.out.println("\nRelease Date: "+instance.parseFirstReleaseDate(releaseDoc)); 273 System.out.println("\nRelease Year: "+instance.parseFirstReleaseYear(releaseDoc)); 274 275 System.out.println("\n\n"+"Artist\n~~~~~~~~~~~~~~~~"); 276 System.out.println(Util.xmlToPrettyString(artistResults, 2)); 277 nu.xom.Document artistDoc = instance.parseXMLResponse(artistResults); 278 279 System.out.println("\n\n"+"Search\n~~~~~~~~~~~~~~~~"); 280 System.out.println(Util.xmlToPrettyString(searchResults, 2)); 281 nu.xom.Document searchDoc = instance.parseXMLResponse(searchResults); 282 } 283 catch (Exception ex) 284 { 285 ex.printStackTrace(); 286 System.out.println("\nParsing error - raw results:"); 287 System.out.println(releaseResults); 288 } 289 } 290 /* *************************************** */ 291 else if (args[0].equalsIgnoreCase("status")) 292 { 293 instance.getStatus(); 294 } 295 /* *************************************** */ 296 else if (args[0].equalsIgnoreCase("parseDir")) 297 { 298 System.out.println(" Parsing current dir AND creating meta-data files."); 299 instance.parseTunesDir("."); 300 } 301 /* *************************************** */ 302 else 303 { 304 instance.restCMD(args); 305 } 306 } 307 } // main 308 309 310 311 /** Parses the tunes dir and reads in all the artists. **/ 312 public void parseTunesDir(String tunesDirPath) 313 { 314 File[] artistDirFiles = (new File( tunesDirPath)).listFiles(); 315 //java.util.List<Track> pagedLovedTracks = (java.util.List<Track>)lastFmLovedTracks_.getPageResults(); 316 if(artistDirFiles!=null) 317 { 318 Vector <MusicbrainzArtist> artists = new Vector <MusicbrainzArtist>(); 319 try 320 { 321 for(File currAristDirFile : artistDirFiles) 322 if(currAristDirFile.isDirectory() 323 && currAristDirFile.canRead() ) 324 { 325 String artName = currAristDirFile.getAbsolutePath().substring(currAristDirFile.getAbsolutePath().lastIndexOf("/")+1); 326 // check if the artist dir has ANY album dirs, then add 327 File[] albumFiles = (new File(currAristDirFile.getAbsolutePath())).listFiles(); 328 boolean valid = false; 329 try 330 { 331 for(int i=0; !valid&&i<albumFiles.length; i++) 332 { 333 // check if there are ANY album dirs 334 if(albumFiles[i].isDirectory() 335 && albumFiles[i].canRead() 336 && albumFiles[i].listFiles().length>0 337 ) valid= true; 338 } 339 if(valid) 340 { 341 MusicbrainzArtist art = new MusicbrainzArtist(Util.capsToSpacesInString(artName), 342 currAristDirFile.getAbsolutePath()); 343 artists.add(art); 344 art.writeMetaData(); 345 art.parseAlbumDirs(); 346 } 347 } 348 catch ( Exception ex) 349 { 350 System.out.println(" *!What The Fudge (parseTunesDir()) : "+ex.getMessage()); 351 ex.printStackTrace(); 352 } 353 } 354 } 355 catch(Exception ex) { /* ignore error dirs */ } 356 artists.sort(MusicbrainzArtist.ArtistComparatorIgnoreCase ); 357 } 358 } 359 360 361 /** 362 * commandLine command executor method for the test Command. 363 * @param args the array of commandLine args that got passed in 364 **/ 365 protected void testCMD(String [] args) 366 { 367 final String methodName = CLASSNAME + ": testCMD(String [])"; 368 369 System.out.println("Testing MusicBrainz Rest Service: "+ "/sys"); 370 StringBuilder resp = serviceGet("/sys"); 371 System.out.println(resp.toString()); System.out.println(); 372 } 373 374 375 protected StringBuilder lookupRelease(String mrid){return lookupRelease(mrid, null);} 376 /** 377 * commandLine command executor method for the test Command. 378 * @param mrid the MusicBrainz Release ID to lookup 379 * @param inc the optional array of associated includes to add to the lookup, null to not add any extra includes 380 **/ 381 public StringBuilder lookupRelease(String mrid, String [] incs) 382 { 383 final String methodName = CLASSNAME + ": lookupRelease(String )"; 384 385 if(debugOut_) System.out.println(" MusicBrainz Rest Service: "+ "lookup a RELEASE"); 386 String inc = ""; 387 if(incs!=null && incs.length >0 && !"".equals(incs[0])) 388 { 389 int cnt = 0; 390 inc = "?inc="; 391 for (String i : incs) 392 { 393 if(cnt++>0) inc+="+"; 394 inc+=i; 395 } 396 if(debugOut_) System.out.println(" with includes="+inc); 397 } 398 StringBuilder resp = serviceGet("/release/"+mrid+inc.replace(" " ,"+")); 399 //if(debugOut_) System.out.println(resp.toString()); if(debugOut_) System.out.println(); 400 return resp; 401 } 402 403 404 /** 405 * Wraps the MusicBrainz search, specifically for a release ; example: https://musicbrainz.org/ws/2/release/?query=release:Gordon%20AND%20artist:Barenaked%20Ladies . 406 * if you want only area=Canada : ID=71bbafaa-e825-3e15-8ca9-017dcad1748b<br> 407 * try https://musicbrainz.org/ws/2/release/?query=release:Gordon%20AND%20country:CA%20AND%20artist:Barenaked+Ladies 408 * @param Artist the artistName of teh release 409 * @param release the name of the release 410 * @return the search results in MMD - MusicBrainz XML Metadata Format (https://musicbrainz.org/doc/MusicBrainz_XML_Meta_Data) 411 **/ 412 public StringBuilder searchRelease(String artist, String release) 413 { 414 final String methodName = CLASSNAME + ": searchRelease(String , String)"; 415 StringBuilder resp = null; 416 //debugOut_=true; 417 418 if(debugOut_) System.out.println(" MusicBrainz Rest Service: "+ "search for a RELEASE"); 419 if(artist!=null && release!=null 420 && !"".equals(artist) && !"".equals(release) ) 421 { 422 try 423 { 424 String searchRequest = "/release/?query=release:"+ 425 URLEncoder.encode(release, "UTF-8")+ 426 "%20AND%20artist:"+ 427 URLEncoder.encode(artist, "UTF-8"); 428 if(debugOut_) System.out.println(" searchRequest= "+searchRequest); 429 resp = serviceGet(searchRequest); 430 431 } 432 catch(java.io.UnsupportedEncodingException ueEx) 433 { 434 ueEx.printStackTrace(); 435 } 436 } 437 //if(debugOut_) System.out.println(resp.toString()); if(debugOut_) System.out.println(); 438 //debugOut_=false; 439 return resp; 440 } 441 442 443 /** 444 * Wraps the MusicBrainz search, specifically for an Artist ; example: https://musicbrainz.org/ws/2/release/?query=release:Gordon%20AND%20artist:Barenaked%20Ladies . 445 * if you want only area=Canada : ID=71bbafaa-e825-3e15-8ca9-017dcad1748b<br> 446 * try https://musicbrainz.org/ws/2/release/?query=release:Gordon%20AND%20country:CA%20AND%20artist:Barenaked+Ladies 447 * @param Artist the artistName of teh release 448 * @return the search results in MMD - MusicBrainz XML Metadata Format (https://musicbrainz.org/doc/MusicBrainz_XML_Meta_Data) 449 **/ 450 public StringBuilder searchArtist(String artist) 451 { 452 final String methodName = CLASSNAME + ": searchArtist("+artist+")"; 453 StringBuilder resp = null; 454 455 if(debugOut_) System.out.println(" MusicBrainz Rest Service: "+ "search for an ARTIST"); 456 if(artist!=null 457 && !"".equals(artist) ) 458 { 459 try 460 { 461 String searchRequest = "/artist/?query=artist:"+ 462 URLEncoder.encode(artist, "UTF-8"); 463 if(debugOut_) System.out.println(" searchRequest= "+searchRequest); 464 resp = serviceGet(searchRequest); 465 466 } 467 catch(java.io.UnsupportedEncodingException ueEx) 468 { 469 ueEx.printStackTrace(); 470 } 471 } 472 //if(debugOut_) System.out.println(resp.toString()); if(debugOut_) System.out.println(); 473 //debugOut_=false; 474 return resp; 475 } 476 477 478 protected StringBuilder lookupArtist(String mrid){return lookupArtist(mrid, null);} 479 /** 480 * commandLine command executor method for the test Command. 481 * @param mrid the MusicBrainz Release ID to lookup 482 * @param inc the optional array of associated includes to add to the lookup, null to not add any extra includes 483 **/ 484 public StringBuilder lookupArtist(String mrid, String [] incs) 485 { 486 final String methodName = CLASSNAME + ": lookupArtist(String )"; 487 488 if(debugOut_) System.out.println(" MusicBrainz Rest Service: "+ "lookup an ARTIST"); 489 String inc = ""; 490 if(incs!=null && incs.length >0 && !"".equals(incs[0])) 491 { 492 int cnt = 0; 493 inc = "?inc="; 494 for (String i : incs) 495 { 496 if(cnt++>0) inc+="+"; 497 inc+=i; 498 } 499 } 500 StringBuilder resp = serviceGet("/artist/"+mrid+inc.replace(" " ,"+")); 501 //if(debugOut_) System.out.println(resp.toString()); if(debugOut_) System.out.println(); 502 return resp; 503 } 504 505 506 public nu.xom.Document parseXMLResponse(String respXmlStr) 507 { 508 //String methodName = className_+"."+Util.getCurrentMethodName(); 509 //log_.startMethod(methodName); 510 if(debugOut_) System.out.println(" parseXMLResponse(String) "); 511 512 nu.xom.Document respDoc = null; 513 nu.xom.Element rootElem = null; 514 try 515 { 516 respDoc = xmlBuilder_.build(respXmlStr,null); 517 } 518 catch (nu.xom.ParsingException xomEx) 519 { 520 xomEx.printStackTrace(); 521 System.out.println("MAJor Error: parsing respXmlStr"); 522 System.out.println(respXmlStr); 523 } 524 catch (IOException ioEx) 525 { 526 ioEx.printStackTrace(); 527 System.out.println("MAJor Error: IOException respXmlStr"); 528 System.out.println(respXmlStr); 529 } 530 return respDoc; 531 } 532 533 534 public java.util.Date parseFirstReleaseDate(nu.xom.Document respDoc){return parseReleaseDate(respDoc, 0);} 535 public java.util.Date parseReleaseDate(nu.xom.Document respDoc, int releaseIndex) 536 { 537 java.util.Date retVal = null; 538 nu.xom.Element rootElem = null; 539 nu.xom.Element dateXpathElem = null; 540 String dateStr = ""; 541 542 if(debugOut_) System.out.println(" > parseReleaseDate not null?"+(respDoc!=null)); 543 if (respDoc!=null) 544 { 545 rootElem = respDoc.getRootElement(); 546 547 nu.xom.Elements releaseEventElems = parseReleaseEventElems(respDoc); 548 nu.xom.Element releaseEventElem = null; //("release-event"); 549 int numReleases = 0; 550 for (int i=0; i< releaseEventElems.size(); i++) 551 { 552 releaseEventElem = releaseEventElems.get(i); //release-event 553 if(releaseEventElem.getLocalName().equalsIgnoreCase("release-event") ) 554 { 555 if(numReleases==releaseIndex) i=releaseEventElems.size(); 556 numReleases++; 557 } 558 } 559 if (releaseEventElem!=null ) 560 { 561 if(debugOut_) System.out.print(" ."); 562 nu.xom.Elements dateElems = releaseEventElem.getChildElements(); 563 nu.xom.Element dateElem = dateElems.get(0); //("date"); 564 dateStr = dateElem.getValue(); 565 if(debugOut_) System.out.print(" "+dateStr); 566 if(debugOut_) System.out.println(" "+Integer.parseInt(dateStr.substring(0,4))+" "+ 567 Integer.parseInt(dateStr.substring(5,7))+" "+ 568 Integer.parseInt(dateStr.substring(8,10))); 569 if (dateElem!=null ) retVal = new java.util.Date(Integer.parseInt(dateStr.substring(0,4))-1900, 570 Integer.parseInt(dateStr.substring(5,7)), 571 Integer.parseInt(dateStr.substring(8,10))); 572 } 573 } 574 if(debugOut_) System.out.println(); 575 return retVal; 576 } 577 578 579 public int parseFirstReleaseYear(nu.xom.Document respDoc){return parseReleaseYear(respDoc, 0);} 580 public int parseReleaseYear(nu.xom.Document respDoc, int releaseIndex) 581 { 582 int retVal = 0; 583 nu.xom.Element rootElem = null; 584 585 if(debugOut_) System.out.println(" > parseReleaseYear not null?"+(respDoc!=null)); 586 if (respDoc!=null) 587 { 588 nu.xom.Elements releaseEventElems = parseReleaseEventElems(respDoc); 589 nu.xom.Element releaseEventElem = null; //("release-event"); 590 for (int i=0; i< releaseEventElems.size(); i++) 591 { 592 releaseEventElem = releaseEventElems.get(i); //release-event 593 if(releaseEventElem.getLocalName().equalsIgnoreCase("release-event")) 594 i=releaseEventElems.size(); 595 } 596 if (releaseEventElem!=null ) 597 { 598 if(debugOut_) System.out.print(" ."); 599 nu.xom.Elements dateElems = releaseEventElem.getChildElements(); 600 nu.xom.Element dateElem = dateElems.get(0); //("date"); 601 if (dateElem!=null ) 602 { 603 String dateStr = dateElem.getValue(); 604 if(debugOut_) System.out.print(" "+dateStr); 605 retVal = Integer.parseInt(dateStr.substring(0,4)); 606 } 607 } 608 } 609 if(debugOut_) System.out.println(); 610 return retVal; 611 } 612 613 614 public nu.xom.Elements parseReleaseEventElems(nu.xom.Document respDoc) 615 { 616 nu.xom.Elements retVal = null; 617 nu.xom.Element rootElem = null; 618 619 if(debugOut_) System.out.println(" > parseReleaseEventElems not null?"+(respDoc!=null)); 620 if (respDoc!=null) 621 { 622 rootElem = respDoc.getRootElement(); 623 // load the data 624 if (rootElem != null && rootElem instanceof Element && rootElem.getLocalName().equals("metadata")) 625 { 626 if(debugOut_) System.out.print(" ."); 627 nu.xom.Elements releaseElems = rootElem.getChildElements(); 628 nu.xom.Element releaseElem = releaseElems.get(0); 629 if (releaseElem!=null ) 630 { 631 if(debugOut_) System.out.print(" ."); 632 nu.xom.Elements releaseEventListElems = releaseElem.getChildElements(); 633 nu.xom.Element releaseEventListElem = null; 634 for (int i=0; i< releaseEventListElems.size(); i++) 635 { 636 releaseEventListElem = releaseEventListElems.get(i); //release-event-list 637 if(releaseEventListElem.getLocalName().equalsIgnoreCase("release-event-list")) 638 i=releaseEventListElems.size(); 639 //releaseEventListElem = releaseElem.getFirstChildElement("release-event-list"); 640 } 641 if (releaseEventListElem!=null ) 642 { 643 if(debugOut_) System.out.print(" ." ); 644 retVal = releaseEventListElem.getChildElements(); 645 } 646 } 647 } 648 } 649 return retVal; 650 } 651 652 653 public nu.xom.Element parseFirstReleaseEventElem(nu.xom.Document respDoc){return parseReleaseEventElem(respDoc, 0);} 654 public nu.xom.Element parseReleaseEventElem(nu.xom.Document respDoc, int releaseIndex) 655 { 656 nu.xom.Element retVal = null; 657 nu.xom.Element rootElem = null; 658 659 if(debugOut_) System.out.println(" > parseReleaseEventElem not null?"+(respDoc!=null)); 660 if (respDoc!=null) 661 { 662 rootElem = respDoc.getRootElement(); 663 664 nu.xom.Elements releaseEventElems = parseReleaseEventElems(respDoc); 665 nu.xom.Element releaseEventElem = null; //("release-event"); 666 int numReleases = 0; 667 for (int i=0; i< releaseEventElems.size(); i++) 668 { 669 releaseEventElem = releaseEventElems.get(i); //release-event 670 if(releaseEventElem.getLocalName().equalsIgnoreCase("release-event") ) 671 { 672 if(numReleases==releaseIndex) 673 { 674 i=releaseEventElems.size(); 675 retVal = releaseEventElem; 676 } 677 numReleases++; 678 } 679 } 680 } 681 682 return retVal; 683 } 684 685 686 public int parseSearchResultsForReleaseYear(nu.xom.Document respDoc) 687 { 688 int retVal = 1900; 689 nu.xom.Element rootElem = null; 690 691 if(debugOut_) System.out.println(" > parseReleaseEventElems not null?"+(respDoc!=null)); 692 if (respDoc!=null) 693 { 694 rootElem = respDoc.getRootElement(); 695 // load the data 696 if (rootElem != null && rootElem instanceof Element && rootElem.getLocalName().equals("metadata")) 697 { 698 if(debugOut_) System.out.print(" ."); 699 nu.xom.Elements releaseListElems = rootElem.getChildElements(); 700 nu.xom.Element releaseListElem = releaseListElems.get(0); 701 if (releaseListElem!=null ) 702 { 703 if(debugOut_) System.out.print(" ."); 704 nu.xom.Elements releaseElems = releaseListElem.getChildElements(); 705 nu.xom.Element releaseElem = null; 706 //for (int i=0; i< releaseElems.size(); i++) 707 //{ 708 releaseElem = releaseElems.get(0); //release-event-list 709 if (releaseElem!=null ) 710 { 711 if(debugOut_) System.out.print(" ."); 712 if(debugOut_) System.out.print(" ("+releaseElem.getLocalName()+")"); 713 nu.xom.Elements releaseSubElems = releaseElem.getChildElements(); 714 nu.xom.Element dateElem = null; 715 boolean foundIt = false; 716 for (int i=0; i< releaseSubElems.size(); i++) 717 { 718 dateElem = releaseSubElems.get(i); 719 if(dateElem.getLocalName().equalsIgnoreCase("date")) 720 { 721 foundIt = true; 722 i=releaseSubElems.size(); 723 } 724 } 725 if (foundIt) 726 { 727 if(debugOut_) System.out.print(" ." ); 728 String dateStr = dateElem.getValue(); 729 if(debugOut_) System.out.print(" "+dateStr); 730 retVal = Integer.parseInt(dateStr.substring(0,4)); 731 } 732 } 733 } 734 } 735 } 736 if(debugOut_) System.out.println("\n >>>>>>>>>>>>>>>>>>>>>>>>>>"); 737 return retVal; 738 } 739 740 741 public nu.xom.Element parseSearchResultsForFirstReleaseElem(nu.xom.Document respDoc) 742 { 743 return parseSearchResultsForReleaseElem(respDoc, 0); 744 } 745 746 747 public nu.xom.Element parseSearchResultsForReleaseElem(nu.xom.Document respDoc, int releaseIndex) 748 { 749 nu.xom.Element retVal = null; 750 nu.xom.Element rootElem = null; 751 752 if(debugOut_) System.out.println(" > parseSearchResultsForReleaseElem["+releaseIndex+"] not null?"+(respDoc!=null)); 753 if (respDoc!=null) 754 { 755 rootElem = respDoc.getRootElement(); 756 // load the data 757 if (rootElem != null && rootElem instanceof Element && rootElem.getLocalName().equals("metadata")) 758 { 759 if(debugOut_) System.out.print(" ."); 760 try 761 { 762 nu.xom.Elements releaseListElems = rootElem.getChildElements(); 763 nu.xom.Element releaseListElem = releaseListElems.get(0); 764 if (releaseListElem!=null ) 765 { 766 if(debugOut_) System.out.print(" ."); 767 nu.xom.Elements releaseElems = releaseListElem.getChildElements(); 768 nu.xom.Element releaseElem = null; 769 releaseElem = releaseElems.get(releaseIndex); //release 770 771 if(debugOut_) System.out.print(" . found: "+releaseElem.getLocalName()); 772 retVal = releaseElem; 773 } 774 } 775 catch (Exception ex) 776 { 777 System.out.print(" NOT found: ["+releaseIndex+"]"); 778 retVal = null; 779 ex.printStackTrace(); 780 } 781 } 782 } 783 if(debugOut_) System.out.println("\n >>>>>>>>>>>>>>>>>>>>>>>>>>"); 784 return retVal; 785 } 786 787 788 /** 789 * Parses through the Release search results doc, gets the 1st release 790 * and looks for the status subElement. 791 * 792 **/ 793 public String parseSearchResultsForFirstReleaseStatus(nu.xom.Document respDoc) 794 { 795 return parseSearchResultsForReleaseStatus(respDoc, 0); 796 } 797 798 799 /** 800 * Parses through the Release search results doc, gets the 1st release 801 * and looks for the status subElement. 802 * 803 **/ 804 public String parseSearchResultsForReleaseStatus(nu.xom.Document respDoc, int releaseIndex) 805 { 806 return parseSearchResultsForReleaseSubElement(respDoc, releaseIndex, "status"); 807 } 808 809 810 /** 811 * Parses through the Release search results doc, gets the 1st release 812 * and looks for the subElement named elemntName passed into this method. 813 * 814 **/ 815 public String parseSearchResultsForFirstReleaseSubElement(nu.xom.Document respDoc, String elementName) 816 { 817 return parseSearchResultsForReleaseSubElement(respDoc, 0, elementName); 818 } 819 820 821 /** 822 * Parses through the search results doc, gets the releaseIndex specified release 823 * and looks for the subElement named elemntName passed into this method. 824 * 825 **/ 826 public String parseSearchResultsForReleaseSubElement(nu.xom.Document respDoc, int releaseIndex, String elementName) 827 { 828 String retVal = null; 829 nu.xom.Element rootElem = null; 830 831 if(debugOut_) System.out.println(" > parseSearchResultsForReleaseSubElement not null?"+(respDoc!=null)); 832 if (respDoc!=null) 833 { 834 rootElem = respDoc.getRootElement(); 835 // load the data 836 if (rootElem != null && rootElem instanceof Element && rootElem.getLocalName().equals("metadata")) 837 { 838 if(debugOut_) System.out.print(" ."); 839 nu.xom.Elements releaseListElems = rootElem.getChildElements(); 840 nu.xom.Element releaseListElem = releaseListElems.get(0); 841 if (releaseListElem!=null ) 842 { 843 if(debugOut_) System.out.print(" ."); 844 nu.xom.Elements releaseElems = releaseListElem.getChildElements(); 845 nu.xom.Element releaseElem = null; 846 //for (int i=0; i< releaseElems.size(); i++) 847 //{ 848 releaseElem = releaseElems.get(releaseIndex); //release-event-list 849 if (releaseElem!=null ) 850 { 851 if(debugOut_) System.out.print(" ."); 852 if(debugOut_) System.out.print(" ( "+releaseElem.getLocalName()); 853 nu.xom.Elements releaseSubElems = releaseElem.getChildElements(); 854 nu.xom.Element subElem = null; 855 boolean foundIt = false; 856 for (int i=0; i< releaseSubElems.size(); i++) 857 { 858 subElem = releaseSubElems.get(i); 859 if(subElem.getLocalName().equalsIgnoreCase(elementName)) 860 { 861 foundIt = true; 862 i=releaseSubElems.size(); 863 } 864 } 865 if (foundIt) 866 { 867 if(debugOut_) System.out.print("/"+elementName+" ) - " ); 868 String elemValueStr = subElem.getValue(); 869 if(debugOut_) System.out.print(" "+elemValueStr); 870 retVal = elemValueStr; 871 } 872 } 873 } 874 } 875 } 876 if(debugOut_) System.out.println("\n >>>>>>>>>>>>>>>>>>>>>>>>>>"); 877 return retVal; 878 } 879 880 881 /** 882 * commandLine command executor method for the default rest Command. 883 * It treats each arg as a part of a single rest command and passes it along to the ISY. 884 * @param args the array of commandLine args that got passed in 885 **/ 886 protected void restCMD(String [] args) 887 { 888 final String methodName = CLASSNAME + ": restCMD(String [])"; 889 // Parse the command 890 String allcommands = args[0]; 891 for (int i=1;i< args.length;i++) allcommands+=" "+args[i]; 892 if (debugOut_) System.out.print("Sending MusicBrainz Rest Service: "+allcommands); 893 String passedCommand = (allcommands.startsWith(restUrlPath_+"/")?allcommands.substring(restUrlPath_.length()):allcommands); 894 if(debugOut_) System.out.println(" ("+passedCommand+")"); 895 passedCommand = (passedCommand.startsWith("/")?passedCommand:"/"+passedCommand); 896 StringBuilder resp = serviceGet(passedCommand); 897 if (resp!=null) 898 { 899 System.out.println(responseIndenter(resp).toString()); 900 System.out.println(); 901 } 902 else 903 { 904 System.out.println("Response Error"); 905 System.out.println(); 906 } 907 908 } 909 910 911 /** 912 * Template method for future commandLine command executor methods. 913 * @param args the array of commandLine args that got passed in 914 **/ 915 protected void templateCMD(String [] args) 916 { 917 final String methodName = CLASSNAME + ": testCMD(String [])"; 918 919 } 920 921 922 /** gets the help as a String. 923 * @return the helpMsg in String form 924 **/ 925 protected static String getHelpMsgStr() {return getHelpMsg().toString();} 926 927 928 /** Makes the JSON string pretty with indenting. **/ 929 public static String prettyJson(String jsonStr) 930 { 931 String retVal = jsonStr; 932 retVal = retVal.replace("[", " [\n"); 933 retVal = retVal.replace("]", " ]" + SYSTEM_LINE_SEPERATOR); 934 retVal = retVal.replace("]\n\"", " ]\"" + SYSTEM_LINE_SEPERATOR); 935 retVal = retVal.replace("{", " {" + SYSTEM_LINE_SEPERATOR + " "); 936 retVal = retVal.replace("}", "}" + SYSTEM_LINE_SEPERATOR); 937 retVal = retVal.replace(",", "," + SYSTEM_LINE_SEPERATOR + " "); 938 retVal = retVal.replace("}" + SYSTEM_LINE_SEPERATOR + "," + SYSTEM_LINE_SEPERATOR, " }," + SYSTEM_LINE_SEPERATOR); 939 retVal = retVal.replace("[\n", " [ "); 940 retVal = retVal.replace(" {", " {"); 941 retVal = retVal.replace("[ {", "[\n {"); 942 retVal = retVal.replace("\n}", "\n }"); 943 return retVal; 944 } 945 946 947 948 /** initializes and gets the helpMsg_ 949 class var. 950 * @return the class var helpMsg_ 951 **/ 952 protected static StringBuilder getHelpMsg() 953 { 954 helpMsg_ = new StringBuilder(SYSTEM_LINE_SEPERATOR); 955 helpMsg_.append("--- WebARTS "+CLASSNAME+" Class -----------------------------------------------------"); 956 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 957 helpMsg_.append("--- + $Revision: 1219 $ $Date: 2018-03-02 22:12:45 -0800 (Fri, 02 Mar 2018) $ ---"); 958 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 959 helpMsg_.append("-------------------------------------------------------------------------------"); 960 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 961 helpMsg_.append("WebARTS ca.bc.webarts.tools.MusicBrainzRestRequester Class"); 962 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 963 helpMsg_.append("SYNTAX:"); 964 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 965 helpMsg_.append(" java "); 966 helpMsg_.append(CLASSNAME); 967 helpMsg_.append(" command or {restCommand}"); 968 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 969 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 970 helpMsg_.append("Available commands:"); 971 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 972 helpMsg_.append(" test"); 973 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 974 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 975 helpMsg_.append(" parseDir"); 976 helpMsg_.append(" Creates MusicBrainz Meta-data files for all subdirectories."); 977 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 978 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 979 helpMsg_.append("Available restCommands:"); 980 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 981 helpMsg_.append(" see: https://musicbrainz.org/doc/Development/XML_Web_Service/Version_2"); 982 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 983 helpMsg_.append(" Example: java ca.bc.webarts.MusicBrainzRestRequester test "); 984 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 985 helpMsg_.append("---------------------------------------------------------"); 986 helpMsg_.append("----------------------"); 987 helpMsg_.append(SYSTEM_LINE_SEPERATOR); 988 989 return helpMsg_; 990 } 991 992} 993 994 /** 995 * 996 * 997 * Musicbrainz Artist Class Object<br> 998 * ~~~~~~~~~~~~~~~~ 999 * representing the returned XML from the mb api query 1000 *<pre> 1001 <?xml version="1.0" encoding="UTF-8"?> 1002 <metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#"> 1003 <artist id="86e736b4-93e2-40ff-9e1c-fb7c63fef5f6" type="Group" type-id="e431f5f6-b5d2-343d-8b36-72607fffb74b"> 1004 <name>Barenaked Ladies</name> 1005 <sort-name>Barenaked Ladies</sort-name> 1006 <isni-list> 1007 <isni>0000000109413643</isni> 1008 </isni-list> 1009 <country>CA</country> 1010 <area id="71bbafaa-e825-3e15-8ca9-017dcad1748b"> 1011 <name>Canada</name> 1012 <sort-name>Canada</sort-name> 1013 <iso-3166-1-code-list> 1014 <iso-3166-1-code>CA</iso-3166-1-code> 1015 </iso-3166-1-code-list> 1016 </area> 1017 <begin-area id="74b24e62-d2fe-42d2-9d96-31f2da756c77"> 1018 <name>Toronto</name> 1019 <sort-name>Toronto</sort-name> 1020 </begin-area> 1021 <life-span> 1022 <begin>1988</begin> 1023 </life-span> 1024 </artist> 1025 </metadata> 1026 </pre> 1027 * 1028 **/ 1029 class MusicbrainzArtist implements Comparable<MusicbrainzArtist> 1030 { 1031 boolean debugOut_ = MusicBrainzRestRequester.debugOut_; 1032 String name = ""; 1033 String id = ""; 1034 String sortName = ""; 1035 String country = ""; 1036 MusicbrainzArea area = null; 1037 String metaDataDirFilename_ = ""; 1038 String metaDataFilename_ = "mbData.props"; 1039 1040 String propsString = ""; 1041 String mbSearchResults_ = ""; 1042 nu.xom.Document mbSearchResultsDoc_ = null; 1043 1044 1045 public MusicbrainzArtist(String artName) 1046 { 1047 name = artName.trim(); 1048 sortName = name; 1049 } 1050 1051 1052 public MusicbrainzArtist(String artName, String metaDataDirFilename) 1053 { 1054 if(debugOut_) System.out.println("\n >>> Creating NEW MusicbrainzArtist\n---------------------------------\n"); 1055 name = artName.trim(); 1056 sortName = name; 1057 metaDataDirFilename_ = metaDataDirFilename; 1058 MusicBrainzRestRequester mbRR = new MusicBrainzRestRequester(); 1059 mbSearchResults_ = mbRR.searchArtist(name).toString(); 1060 try 1061 { 1062 mbSearchResultsDoc_ = mbRR.parseXMLResponse(mbSearchResults_); 1063 parseFirstArtistElem(mbSearchResultsDoc_); 1064 if(debugOut_) System.out.println(" MB Search Results:\n"); 1065 if(debugOut_) System.out.println(Util.xmlToPrettyString(mbSearchResults_, 2)); 1066 //parseAlbumDirs(); 1067 } 1068 catch (Exception ex) 1069 { 1070 ex.printStackTrace(); 1071 System.out.println("\nParsing error - raw results:"); 1072 System.out.println(mbSearchResults_); 1073 } 1074 } 1075 1076 1077 public String toString(){return name;} 1078 1079 1080 /** 1081 * Set Method for class field 'sortName'. 1082 * 1083 * @param sortName is the value to set this class field to. 1084 * 1085 **/ 1086 public void setSortName(String sortName) 1087 { 1088 this.sortName = sortName; 1089 } // setSortName Method 1090 1091 1092 /** 1093 * Get Method for class field 'sortName'. 1094 * 1095 * @return String - The value the class field 'sortName'. 1096 * 1097 **/ 1098 public String getSortName() 1099 { 1100 return sortName; 1101 } // getSortName Method 1102 1103 1104 public String getPropsString() 1105 { 1106 String p = "MusicbrainzArtist_"; 1107 String retVal = "#MusicBrainz Artist Properties\n"; 1108 retVal += "# "+Util.createCurrentDateTime()+"\n"; 1109 retVal += p+"name="+name+"\n"; 1110 retVal += p+"sortName="+getSortName()+"\n"; 1111 retVal += p+"id="+id+"\n"; 1112 retVal += p+"country="+country+"\n"; 1113 retVal += p+"metaDataDirFilename="+metaDataDirFilename_+"\n"; 1114 retVal += area.getPropsString(); 1115 1116 return retVal; 1117 } 1118 1119 1120 public void writeMetaData() 1121 { 1122 System.out.println("\nCreating Metadata file for: "+getSortName()); 1123 System.out.println(" Filename: "+metaDataDirFilename_+"/"+metaDataFilename_); 1124 System.out.println(getPropsString()); 1125 if(MusicBrainzRestRequester.doWrites_) Util.writeStringToFile(getPropsString(), metaDataDirFilename_+"/"+metaDataFilename_); 1126 } 1127 1128 1129 public nu.xom.Element parseFirstArtistElem(nu.xom.Document respDoc){return parseArtistElem(respDoc, 0);} 1130 public nu.xom.Element parseArtistElem(nu.xom.Document respDoc, int artistIndex) 1131 { 1132 nu.xom.Element retVal = null; 1133 nu.xom.Element rootElem = null; 1134 1135 if(debugOut_) System.out.println(" > parseArtistElem not null?"+(respDoc!=null)); 1136 if (respDoc!=null) 1137 { 1138 rootElem = respDoc.getRootElement(); 1139 if (rootElem != null && rootElem instanceof Element && rootElem.getLocalName().equals("metadata")) 1140 { 1141 if(debugOut_) System.out.print(" ."); 1142 nu.xom.Elements artistListElems = rootElem.getChildElements(); 1143 nu.xom.Element artistListElem = artistListElems.get(0); 1144 if (artistListElem!=null ) 1145 { 1146 nu.xom.Elements artistElems = artistListElem.getChildElements(); 1147 int numArtists = 0; 1148 if (artistElems!=null ) 1149 { 1150 nu.xom.Element artistElem = null; 1151 for (int i=0; i< artistListElems.size(); i++) 1152 { 1153 if(debugOut_) System.out.print(" ."); 1154 artistElem = artistElems.get(i); 1155 if(artistElem.getLocalName().equalsIgnoreCase("artist") ) 1156 { 1157 if(debugOut_) System.out.print(" ."); 1158 if(numArtists==artistIndex) 1159 { 1160 i=artistListElems.size(); 1161 retVal = artistElem; 1162 id=artistElem.getAttributeValue("id"); 1163 1164 nu.xom.Elements artistSubElems = artistElem.getChildElements(); 1165 if (artistSubElems!=null ) 1166 { 1167 nu.xom.Element currElem = null; 1168 for (int ii=0; ii< artistSubElems.size(); ii++) 1169 { 1170 currElem = artistSubElems.get(ii); 1171 if(currElem.getLocalName().equalsIgnoreCase("sort-name") ) sortName = currElem.getValue(); 1172 if(currElem.getLocalName().equalsIgnoreCase("country") ) country = currElem.getValue(); 1173 if(currElem.getLocalName().equalsIgnoreCase("area") ) 1174 { 1175 //parse the area 1176 area = new MusicbrainzArea(currElem); 1177 } 1178 //if(debugOut_) System.out.print(" subElement "+currElem.getLocalName()); 1179 } 1180 } 1181 } 1182 numArtists++; 1183 } 1184 else 1185 if(debugOut_) System.out.print(" !!! "+artistElem.getLocalName()); 1186 } 1187 } 1188 } 1189 } 1190 } 1191 1192 return retVal; 1193 } 1194 1195 1196 public void parseAlbumDirs() 1197 { 1198 File[] albumDirFiles = (new File( metaDataDirFilename_ )).listFiles(); 1199 //java.util.List<Track> pagedLovedTracks = (java.util.List<Track>)lastFmLovedTracks_.getPageResults(); 1200 boolean valid = false; 1201 if(albumDirFiles!=null) 1202 { 1203 Vector <MusicbrainzRelease> albums = new Vector <MusicbrainzRelease>(); 1204 try 1205 { 1206 for(File currAlbumDirFile : albumDirFiles) 1207 { 1208 valid = false; 1209 if(currAlbumDirFile.isDirectory() 1210 && currAlbumDirFile.canRead() 1211 && currAlbumDirFile.listFiles().length>0 1212 ) valid= true; 1213 { 1214 if(valid) 1215 { 1216 String albName = currAlbumDirFile.getAbsolutePath().substring(currAlbumDirFile.getAbsolutePath().lastIndexOf("/")+1); 1217 MusicbrainzRelease alb = new MusicbrainzRelease(name, 1218 Util.capsToSpacesInString(albName), 1219 currAlbumDirFile.getAbsolutePath()); 1220 albums.add(alb); 1221 alb.writeMetaData(); 1222 } 1223 } 1224 } 1225 } 1226 catch ( Exception ex) 1227 { 1228 System.out.println(" *!What The Fudge (parseAlbumDirs()) : "+ex.getMessage()); 1229 ex.printStackTrace(); 1230 } 1231 albums.sort(MusicbrainzRelease.ReleaseComparatorIgnoreCase ); 1232 } 1233 } 1234 1235 1236 /** Comparator for ignore case sort. **/ 1237 public int compareToIgnoreCase(MusicbrainzArtist other) 1238 { 1239 return this.getSortName().compareToIgnoreCase(other.getSortName()); 1240 } 1241 1242 1243 /** implements Comparator. **/ 1244 @Override public int compareTo(MusicbrainzArtist other) 1245 { 1246 return this.getSortName().compareTo(other.getSortName()); 1247 } 1248 1249 1250 /** A Comparator that can be used to sort Artist vectors. **/ 1251 public static Comparator <MusicbrainzArtist> ArtistComparator = new Comparator<MusicbrainzArtist>() 1252 { 1253 @Override public int compare(MusicbrainzArtist one, MusicbrainzArtist two) 1254 { 1255 return one.getSortName().compareTo(two.getSortName()); 1256 } 1257 }; 1258 1259 1260 /** A case in-sensitive Comparator that can be used to sort MusicbrainzArtist vectors. **/ 1261 public static Comparator <MusicbrainzArtist> ArtistComparatorIgnoreCase = new Comparator<MusicbrainzArtist>() 1262 { 1263 @Override public int compare(MusicbrainzArtist one, MusicbrainzArtist two) 1264 { 1265 //return one.name(true).compareTo(two.name(true)); 1266 return one.getSortName().compareToIgnoreCase(two.getSortName()); 1267 } 1268 }; 1269 1270 } 1271 1272 1273 /** 1274 * 1275 * 1276 * Musicbrainz Release Class Object<br> 1277 * ~~~~~~~~~~~~~~~~ 1278 * representing the returned XML from the mb api query 1279 *<pre> 1280 <?xml version="1.0" encoding="UTF-8"?> 1281 1282 </pre> 1283 * 1284 **/ 1285 class MusicbrainzRelease implements Comparable<MusicbrainzRelease> 1286 { 1287 boolean debugOut_ = MusicBrainzRestRequester.debugOut_; 1288 String artistName_ = ""; 1289 String name = ""; 1290 String id = ""; 1291 String sortName = ""; 1292 String country = ""; 1293 String releaseDate = ""; 1294 int year = 0; 1295 String status = ""; 1296 MusicbrainzArea area = null; 1297 String metaDataDirFilename_ = ""; 1298 String metaDataFilename_ = "mbData.props"; 1299 1300 String propsString = ""; 1301 String mbSearchResults_ = ""; 1302 nu.xom.Document mbSearchResultsDoc_ = null; 1303 1304 1305 public MusicbrainzRelease(String artistName, String albName) 1306 { 1307 artistName_ = artistName; 1308 name = albName.trim(); 1309 sortName = name; 1310 } 1311 1312 1313 public MusicbrainzRelease(String artistName, String albName, String metaDataDirFilename) 1314 { 1315 artistName_ = artistName; 1316 name = albName.trim(); 1317 sortName = name; 1318 metaDataDirFilename_ = metaDataDirFilename; 1319 MusicBrainzRestRequester mbRR = new MusicBrainzRestRequester(); 1320 mbSearchResults_ = mbRR.searchRelease(artistName, name).toString(); 1321 try 1322 { 1323 mbSearchResultsDoc_ = mbRR.parseXMLResponse(mbSearchResults_); 1324 nu.xom.Element firstRelease = mbRR.parseSearchResultsForFirstReleaseElem(mbSearchResultsDoc_); 1325 id=firstRelease.getAttributeValue("id"); 1326 if(debugOut_) System.out.println(" Release ID: "+ id); 1327 if(debugOut_) System.out.println(" MB Search Results:\n"); 1328 if(debugOut_) System.out.println(Util.xmlToPrettyString(mbSearchResults_, 2)); 1329 status=mbRR.parseSearchResultsForFirstReleaseStatus(mbSearchResultsDoc_); 1330 country=mbRR.parseSearchResultsForReleaseSubElement(mbSearchResultsDoc_, 0, "country"); 1331 releaseDate=mbRR.parseSearchResultsForReleaseSubElement(mbSearchResultsDoc_, 0, "date"); 1332 year = Integer.parseInt(releaseDate.substring(0,4)); 1333 } 1334 catch (Exception ex) 1335 { 1336 ex.printStackTrace(); 1337 System.out.println("\n---------------------------------\nParsing error\n - raw results:"); 1338 try {System.out.println(Util.xmlToPrettyString(mbSearchResults_, 2));} 1339 catch (Exception exx) {System.out.println(mbSearchResults_);} 1340 } 1341 } 1342 1343 1344 public String toString(){return name;} 1345 1346 1347 /** 1348 * Set Method for class field 'sortName'. 1349 * 1350 * @param sortName is the value to set this class field to. 1351 * 1352 **/ 1353 public void setSortName(String sortName) 1354 { 1355 this.sortName = sortName; 1356 } // setSortName Method 1357 1358 1359 /** 1360 * Get Method for class field 'sortName'. 1361 * 1362 * @return String - The value the class field 'sortName'. 1363 * 1364 **/ 1365 public String getSortName() 1366 { 1367 return sortName; 1368 } // getSortName Method 1369 1370 1371 public String getPropsString() 1372 { 1373 String p = "MusicbrainzRelease_"; 1374 String retVal = "#MusicBrainz Album Properties\n"; 1375 retVal += "# "+Util.createCurrentDateTime()+"\n"; 1376 retVal += p+"artistName="+artistName_+"\n"; 1377 retVal += p+"name="+name+"\n"; 1378 retVal += p+"sortName="+getSortName()+"\n"; 1379 retVal += p+"id="+id+"\n"; 1380 retVal += p+"country="+country+"\n"; 1381 retVal += p+"date="+releaseDate+"\n"; 1382 retVal += p+"year="+year+"\n"; 1383 retVal += p+"status="+status+"\n"; 1384 retVal += p+"metaDataDirFilename="+metaDataDirFilename_+"\n"; 1385 1386 return retVal; 1387 } 1388 1389 1390 public void writeMetaData() 1391 { 1392 System.out.println("\nCreating Metadata file for: "+getSortName()); 1393 System.out.println(" Filename: "+metaDataDirFilename_+"/"+metaDataFilename_); 1394 System.out.println(getPropsString()); 1395 if(MusicBrainzRestRequester.doWrites_) Util.writeStringToFile(getPropsString(), metaDataDirFilename_+"/"+metaDataFilename_); 1396 } 1397 1398 1399 /** Comparator for ignore case sort. **/ 1400 public int compareToIgnoreCase(MusicbrainzRelease other) 1401 { 1402 return this.getSortName().compareToIgnoreCase(other.getSortName()); 1403 } 1404 1405 1406 /** implements Comparator. **/ 1407 @Override public int compareTo(MusicbrainzRelease other) 1408 { 1409 return this.getSortName().compareTo(other.getSortName()); 1410 } 1411 1412 1413 /** A Comparator that can be used to sort Release vectors. **/ 1414 public static Comparator <MusicbrainzRelease> ReleaseComparator = new Comparator<MusicbrainzRelease>() 1415 { 1416 @Override public int compare(MusicbrainzRelease one, MusicbrainzRelease two) 1417 { 1418 return one.getSortName().compareTo(two.getSortName()); 1419 } 1420 }; 1421 1422 1423 /** A case in-sensitive Comparator that can be used to sort MusicbrainzRelease vectors. **/ 1424 public static Comparator <MusicbrainzRelease> ReleaseComparatorIgnoreCase = new Comparator<MusicbrainzRelease>() 1425 { 1426 @Override public int compare(MusicbrainzRelease one, MusicbrainzRelease two) 1427 { 1428 //return one.name(true).compareTo(two.name(true)); 1429 return one.getSortName().compareToIgnoreCase(two.getSortName()); 1430 } 1431 }; 1432 1433 1434 } 1435 1436 1437 /** 1438 * 1439 * 1440 * Musicbrainz Track Class Object<br> 1441 * ~~~~~~~~~~~~~~~~ 1442 * representing the returned XML from the mb api query 1443 *<pre> 1444 <?xml version="1.0" encoding="UTF-8"?> 1445 1446 </pre> 1447 * 1448 **/ 1449 class MusicbrainzTrack 1450 { 1451 } 1452 1453 1454 /** 1455 * 1456 * 1457 * Musicbrainz Area/region Class Object<br> 1458 * ~~~~~~~~~~~~~~~~ 1459 * representing the returned XML from the mb api query 1460 *<pre> 1461 <?xml version="1.0" encoding="UTF-8"?> 1462 1463 </pre> 1464 * 1465 **/ 1466 class MusicbrainzArea implements Comparable<MusicbrainzArea> 1467 { 1468 String name = ""; 1469 String id = ""; 1470 String sortName = ""; 1471 String iso31661code = ""; 1472 1473 public MusicbrainzArea() 1474 { 1475 } 1476 1477 1478 public MusicbrainzArea(String areaName) 1479 { 1480 name = areaName; 1481 sortName = name; 1482 } 1483 1484 1485 public MusicbrainzArea(nu.xom.Element areaElem ) 1486 { 1487 try 1488 { 1489 // parse the area info from the Element 1490 if (areaElem!=null ) 1491 { 1492 if(areaElem.getLocalName().equalsIgnoreCase("area") ) 1493 { 1494 id=areaElem.getAttributeValue("id"); 1495 1496 nu.xom.Elements areaSubElems = areaElem.getChildElements(); 1497 if (areaSubElems!=null ) 1498 { 1499 nu.xom.Element currElem = null; 1500 for (int ii=0; ii< areaSubElems.size(); ii++) 1501 { 1502 currElem = areaSubElems.get(ii); 1503 if(currElem.getLocalName().equalsIgnoreCase("sort-name") ) sortName = currElem.getValue(); 1504 if(currElem.getLocalName().equalsIgnoreCase("name") ) name = currElem.getValue(); 1505 } 1506 } 1507 } 1508 else 1509 System.out.print(" !!! "+areaElem.getLocalName()); 1510 } 1511 } 1512 catch (Exception ex) 1513 { 1514 ex.printStackTrace(); 1515 System.out.println("\nParsing error - Area raw results:"); 1516 System.out.println(areaElem); 1517 } 1518 } 1519 1520 1521 public String toString(){return name;} 1522 1523 1524 public String getPropsString() 1525 { 1526 String p = "MusicbrainzArea_"; 1527 String retVal = "#MusicBrainz Area Properties\n"; 1528 retVal += p+"name="+name+"\n"; 1529 retVal += p+"sortName="+getSortName()+"\n"; 1530 retVal += p+"id="+id+"\n"; 1531 retVal += p+"iso31661code="+iso31661code+"\n"; 1532 1533 return retVal; 1534 } 1535 1536 1537 1538 /** 1539 * Set Method for class field 'sortName'. 1540 * 1541 * @param sortName is the value to set this class field to. 1542 * 1543 **/ 1544 public void setSortName(String sortName) 1545 { 1546 this.sortName = sortName; 1547 } // setSortName Method 1548 1549 1550 /** 1551 * Get Method for class field 'sortName'. 1552 * 1553 * @return String - The value the class field 'sortName'. 1554 * 1555 **/ 1556 public String getSortName() 1557 { 1558 return sortName; 1559 } // getSortName Method 1560 1561 1562 /** Comparator for ignore case sort. **/ 1563 public int compareToIgnoreCase(MusicbrainzArea other) 1564 { 1565 return this.getSortName().compareToIgnoreCase(other.getSortName()); 1566 } 1567 1568 1569 /** implements Comparator. **/ 1570 @Override public int compareTo(MusicbrainzArea other) 1571 { 1572 return this.getSortName().compareTo(other.getSortName()); 1573 } 1574 1575 1576 /** A Comparator that can be used to sort Artist vectors. **/ 1577 public static Comparator <MusicbrainzArea> ArtistComparator = new Comparator<MusicbrainzArea>() 1578 { 1579 @Override public int compare(MusicbrainzArea one, MusicbrainzArea two) 1580 { 1581 return one.getSortName().compareTo(two.getSortName()); 1582 } 1583 }; 1584 1585 1586 /** A case in-sensitive Comparator that can be used to sort MusicbrainzArtist vectors. **/ 1587 public static Comparator <MusicbrainzArea> AreaComparatorIgnoreCase = new Comparator<MusicbrainzArea>() 1588 { 1589 @Override public int compare(MusicbrainzArea one, MusicbrainzArea two) 1590 { 1591 //return one.name(true).compareTo(two.name(true)); 1592 return one.getSortName().compareToIgnoreCase(two.getSortName()); 1593 } 1594 }; 1595 } 1596 1597 1598 /** 1599 * 1600 * 1601 * Musicbrainz Begin Class Object<br> 1602 * ~~~~~~~~~~~~~~~~ 1603 * representing the returned XML from the mb api query 1604 *<pre> 1605 <?xml version="1.0" encoding="UTF-8"?> 1606 1607 </pre> 1608 * 1609 **/ 1610 class MusicbrainzBeginArea 1611 { 1612 } 1613 1614 1615 /** 1616 * 1617 * 1618 * Musicbrainz Life-span Class Object<br> 1619 * ~~~~~~~~~~~~~~~~ 1620 * representing the returned XML from the mb api query 1621 *<pre> 1622 <?xml version="1.0" encoding="UTF-8"?> 1623 1624 </pre> 1625 * 1626 **/ 1627 class MusicbrainzLifespan 1628 { 1629 }