Java tutorial
package org.fnppl.opensdx.dmi.wayin; import java.io.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import org.fnppl.opensdx.common.*; import org.fnppl.opensdx.dmi.GenreConverter; import org.fnppl.opensdx.xml.*; import org.fnppl.opensdx.security.*; import org.jdom2.Namespace; /* * Copyright (C) 2010-2015 * fine people e.V. <opensdx@fnppl.org> * Henning Thie <ht@fnppl.org> * * http://fnppl.org */ /* * Software license * * As far as this file or parts of this file is/are software, rather than documentation, this software-license applies / shall be applied. * * This file is part of openSDX * openSDX is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * openSDX is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * and GNU General Public License along with openSDX. * If not, see <http://www.gnu.org/licenses/>. * */ /* * Documentation license * * As far as this file or parts of this file is/are documentation, rather than software, this documentation-license applies / shall be applied. * * This file is part of openSDX. * Permission is granted to copy, distribute and/or modify this document * under the terms of the GNU Free Documentation License, Version 1.3 * or any later version published by the Free Software Foundation; * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. * A copy of the license is included in the section entitled "GNU * Free Documentation License" resp. in the file called "FDL.txt". * */ public class PieToOpenSDXImporter extends OpenSDXImporterBase { DateFormat ymd = new SimpleDateFormat("yyyy-MM-dd"); private boolean forceImport = true; //in case we need to import a takedown xmls, this flag needs to be set on true. private Result ir = Result.succeeded(); // test? boolean onlytest = true; public PieToOpenSDXImporter(ImportType type, File impFile, File savFile) { super(type, impFile, savFile); } public PieToOpenSDXImporter(File impFile) { super(ImportType.getImportType("pie"), impFile, null); } public Result formatToOpenSDXFile() { try { Feed feed = this.getImportFeed(); if (feed != null) { // write file Document doc = Document.buildDocument(feed.toElement()); doc.writeToFile(this.saveFile); } } catch (Exception e) { // e.printStackTrace(); ir.succeeded = false; ir.errorMessage = e.getMessage(); ir.exception = e; } return ir; } private Feed getImportFeed() { // do the import Feed feed = null; try { // (1) get XML-Data from import document Document impDoc = Document.fromFile(this.importFile); Element root = impDoc.getRootElement(); //(1.1) sets the activen namespace for this root element to avoid parameter overhead for all Element getters. root.setActiveNamespace(root.getNamespace()); // (2) get FeedInfo from import and create feedid and new FeedInfo for openSDX String feedid = UUID.randomUUID().toString(); Calendar cal = Calendar.getInstance(); long creationdatetime = cal.getTimeInMillis(); long effectivedatetime = cal.getTimeInMillis(); String lic = root.getChildTextNN("provider"); if (lic.length() == 0) lic = "[NOT SET]"; ContractPartner sender = ContractPartner.make(ContractPartner.ROLE_SENDER, lic, "1"); ContractPartner licensor = ContractPartner.make(ContractPartner.ROLE_LICENSOR, lic, "1"); ContractPartner licensee = ContractPartner.make(ContractPartner.ROLE_LICENSEE, "1", "1"); FeedInfo feedinfo = FeedInfo.make(onlytest, feedid, creationdatetime, effectivedatetime, sender, licensor, licensee); // (3) create new feed with feedinfo feed = Feed.make(feedinfo); // path to importfile String path = this.importFile.getParent() + File.separator; Element album = root.getChild("album"); // Information String streetReleaseDate = album.getChildTextNN("original_release_date"); if (streetReleaseDate.length() > 0) { cal.setTime(ymd.parse(streetReleaseDate)); } else { // MUST: when not provided then today cal.setTime(new Date()); } // streetRelease = physicalRelease (?) long srd = cal.getTimeInMillis(); long prd = cal.getTimeInMillis(); BundleInformation info = BundleInformation.make(srd, prd); // language if (root.getChild("language") != null && root.getChildTextNN("language").length() > 0) { info.main_language(root.getChildText("language").substring(0, 2)); } // IDs of bundle -> more (?) IDs bundleids = IDs.make(); if (album.getChild("upc") != null) bundleids.upc(album.getChildTextNN("upc")); // displayname String displayname = album.getChildTextNN("title"); // display_artistname String display_artistname = null; //album.getChildTextNN("album_display_artist"); //Get first performer Vector<Element> contributors = album.getChild("artists").getChildren("artist"); for (Iterator<Element> itContributors = contributors.iterator(); itContributors.hasNext();) { Element contributor = itContributors.next(); if (contributor.getChild("roles") != null && contributor.getChild("roles").getChild("role") != null) { String role = contributor.getChild("roles").getChildTextNN("role").trim().toLowerCase(); if (role.equals("performer") && "true".equals(contributor.getChildText("primary"))) { display_artistname = contributor.getChildTextNN("artist_name"); break; } } } // license basis Territorial territorial = Territorial.make(); // Release LicenseBasis license_basis = LicenseBasis.make(territorial, srd, prd); // license specifics -> empty! LicenseSpecifics license_specifics = LicenseSpecifics.make(); // receiver -> "MUST" -> empty! Receiver rec = Receiver.make(Receiver.TRANSFER_TYPE_OSDX_FILESERVER); rec.servername("servername"); rec.serveripv4("0.0.0.0"); rec.authtype("login"); rec.username("testuser"); feedinfo.receiver(rec); // Album Territories, Streaming and Download HashMap<String, Element> albumTerritories = new HashMap<String, Element>(); //Global album territories to match with Pies track territories boolean downloadAllowed = false; boolean streamingAllowed = false; //calculate major streaming & sales date HashMap<String, String> majorDates = calculateDateMajorities( album.getChild("products").getChildren("product").iterator()); Element albumProducts = album.getChild("products"); if (albumProducts != null) { Vector<Element> products = albumProducts.getChildren("product"); if (products != null && products.size() > 0) { for (Element p : products) { albumTerritories.put(p.getChildTextNN("territory"), p); //Puts the current territory for later track territory comparison String territory = p.getChildText("territory"); if (forceImport) { //no rules necessary, just import. Download and streaming allowed = true, streaming start & enddate are the regular releasedate downloadAllowed = true; streamingAllowed = true; territorial.allow(territory); } else { downloadAllowed |= p.getChildBoolean("cleared_for_sale", false); streamingAllowed |= p.getChildBoolean("cleared_for_stream", false); if (p.getChildBoolean("cleared_for_sale", false) || p.getChildBoolean("cleared_for_stream", false)) { territorial.allow(territory); //rules in case <sales_start_date> != <stream_start_date> if (!p.getChildTextNN("sales_start_date") .equals(p.getChildTextNN("stream_start_date"))) { //add rule LicenseRule rule = LicenseRule.make(1, "streaming_allowed", "equals", "true"); rule.addThenProclaim("timeframe_from", p.getChildTextNN("sales_start_date")); license_specifics.addRule(rule); } if (!p.getChildTextNN("sales_start_date").equals(majorDates.get("sales"))) { //add rule for sales LicenseRule rule = LicenseRule.make(2, "territory", "equals", territory); rule.addThenProclaim("timeframe_from", majorDates.get("sales")); license_specifics.addRule(rule); } if (!p.getChildTextNN("stream_start_date").equals(majorDates.get("stream"))) { //add rule for streaming LicenseRule rule = LicenseRule.make(3, "territory", "equals", territory); rule.addThenProclaim("streaming_timeframe_from", majorDates.get("stream")); license_specifics.addRule(rule); } } else { territorial.disallow(territory); } } } } } //allow download and streaming based on territories. license_basis.download_allowed(downloadAllowed); license_basis.streaming_allowed(streamingAllowed); Bundle bundle = Bundle.make(bundleids, displayname, displayname, "", display_artistname, info, license_basis, license_specifics); // add contributor label Contributor con = Contributor.make(album.getChildTextNN("label_name"), Contributor.TYPE_LABEL, IDs.make()); bundle.addContributor(con); // add contributor display_artist con = Contributor.make(display_artistname, Contributor.TYPE_DISPLAY_ARTIST, IDs.make()); bundle.addContributor(con); contributors = album.getChild("artists").getChildren("artist"); for (Iterator<Element> itContributors = contributors.iterator(); itContributors.hasNext();) { Element contributor = itContributors.next(); if (contributor.getChild("roles") != null && contributor.getChild("roles").getChild("role") != null) { String role = contributor.getChild("roles").getChildTextNN("role").trim().toLowerCase(); if (role.equals("performer")) { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_PERFORMER, IDs.make()); } else if (role.equals("featuring")) { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_FEATURING, IDs.make()); } else if (role.equals("composer")) { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_COMPOSER, IDs.make()); } else if (role.equals("producer")) { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_PRODUCER, IDs.make()); } // Maybe more roles? Insert! bundle.addContributor(con); } else { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_PERFORMER, IDs.make()); bundle.addContributor(con); } } String copyright = album.getChildTextNN("copyright_cline"); String production = album.getChildTextNN("copyright_pline"); if (copyright.length() > 0) { con = Contributor.make(copyright.substring(5), Contributor.TYPE_COPYRIGHT, IDs.make()); con.year(copyright.substring(0, 4)); bundle.addContributor(con); } if (production.length() > 0) { con = Contributor.make(production.substring(5), Contributor.TYPE_PRODUCTION, IDs.make()); con.year(production.substring(0, 4)); bundle.addContributor(con); } // cover: license_basis & license_specifics from bundle, right? if (album.getChild("artwork_files") != null && album.getChild("artwork_files").getChild("file") != null) { Element cover = album.getChild("artwork_files").getChild("file"); ItemFile itemfile = ItemFile.make(); itemfile.type("frontcover"); // check if file exist at path String filename = cover.getChildTextNN("file_name"); File f = new File(path + filename); if (f != null && f.exists()) { itemfile.setFile(f); // set delivered path to file itemfile.setLocation(FileLocation.make(filename, filename)); } else { //file does not exist -> so we have to set the values "manually" //-> use filename for location itemfile.setLocation(FileLocation.make(filename, filename)); //file size if (cover.getChild("size") != null) { itemfile.bytes(Integer.parseInt(cover.getChildText("size"))); } // checksum md5 if (cover.getChild("checksum") != null) { Element cs = cover.getChild("checksum"); if (cs != null) { if (cs.getAttribute("type").equals("md5")) { String sMd5 = cover.getChildText("checksum"); byte[] md5 = SecurityHelper.HexDecoder.decode(sMd5); itemfile.checksums(Checksums.make().md5(md5)); } } } } bundle.addFile(itemfile); } // init GenreConverter GenreConverter gc = GenreConverter.getInstance(GenreConverter.PIE_TO_OPENSDX); // add Tags ItemTags tags = ItemTags.make(); Vector<Element> genres = album.getChild("genres").getChildren("genre"); for (Iterator<Element> itGenres = genres.iterator(); itGenres.hasNext();) { Element genre = itGenres.next(); tags.addGenre(gc.convert(genre.getAttribute("code"))); } bundle.tags(tags); // Vector<Element> tracks = album.getChild("tracks").getChildren("track"); for (Iterator<Element> itTracks = tracks.iterator(); itTracks.hasNext();) { Element track = itTracks.next(); IDs trackids = IDs.make(); if (track.getChild("isrc") != null) trackids.isrc(track.getChildTextNN("isrc")); // displayname String track_displayname = track.getChildTextNN("title"); // display_artistname / later set this to track artist if available String track_display_artistname = display_artistname; BundleInformation track_info = BundleInformation.make(srd, prd); // num if (track.getChildTextNN("number").length() > 0) { track_info.num(Integer.parseInt(track.getChildText("number"))); } // setnum if (track.getChildTextNN("volume_number").length() > 0) { track_info.setnum(Integer.parseInt(track.getChildText("volume_number"))); } // tracklength if (track.getChildTextNN("duration").length() > 0) { track_info.playlength(Integer.parseInt(track.getChildText("duration"))); } // suggested prelistining offset if (track.getChild("preview_start_index") != null && track.getChildTextNN("preview_start_index").length() > 0) { track_info.suggested_prelistening_offset( Integer.parseInt(track.getChildText("preview_start_index"))); } // track license basis LicenseBasis track_license_basis = LicenseBasis.make(); Territorial track_territorial = Territorial.make(); track_license_basis.setTerritorial(track_territorial); // license specifics -> empty! LicenseSpecifics track_license_specifics = LicenseSpecifics.make(); // license_basis of Bundle / license_specifics of Bundle / others (?) Item item = Item.make(trackids, track_displayname, track_display_artistname, "", "audio", track_display_artistname, track_info, track_license_basis, track_license_specifics); contributors = track.getChild("artists").getChildren("artist"); for (Iterator<Element> itContributors = contributors.iterator(); itContributors.hasNext();) { Element contributor = itContributors.next(); boolean display_artist_isSet = false; if (contributor.getChild("primary") != null) { if (contributor.getChildTextNN("primary").equals("true") && !display_artist_isSet) { item.display_artistname(contributor.getChildTextNN("artist_name")); display_artist_isSet = true; } } if (contributor.getChild("roles") != null && contributor.getChild("roles").getChild("role") != null) { String role = contributor.getChild("roles").getChildTextNN("role").trim().toLowerCase(); if (role.equals("performer")) { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_PERFORMER, IDs.make()); } else if (role.equals("featuring")) { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_FEATURING, IDs.make()); } else if (role.equals("composer")) { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_COMPOSER, IDs.make()); } else if (role.equals("producer")) { con = Contributor.make(contributor.getChildTextNN("artist_name"), Contributor.TYPE_PRODUCER, IDs.make()); } // Maybe more roles? Insert! item.addContributor(con); } else { con = Contributor.make(contributor.getChildTextNN("name"), Contributor.TYPE_PERFORMER, IDs.make()); item.addContributor(con); } } // Check if track territory equal to those on bundle level if (forceImport) { //In case of force import, just like on bundle (Just allow everything) track_license_basis.as_on_bundle(true); } else { boolean asOnBundle = asOnBundle(albumTerritories, track.getChild("products").getChildren("product")); if (asOnBundle) { track_license_basis.as_on_bundle(asOnBundle); } else { //Check track territories again. Vector<Element> tmp = track.getChild("products").getChildren("product"); for (Element t : tmp) { String territory = t.getChildText("territory"); if (t.getChildBoolean("cleared_for_sale", false) || t.getChildBoolean("cleared_for_stream", false)) { track_territorial.allow(territory); } else { track_territorial.disallow(territory); } } } } // add Tags ItemTags track_tags = ItemTags.make(); Vector<Element> track_genres = track.getChild("genres").getChildren("genre"); for (Iterator<Element> itTrackGenres = track_genres.iterator(); itTrackGenres.hasNext();) { Element genre = itTrackGenres.next(); tags.addGenre(gc.convert(genre.getAttribute("code"))); } item.tags(track_tags); Element audioFile = track.getChild("audio_file"); // check if file exist at path (Optional, in case of an update XML this element may be missing) if (audioFile != null) { ItemFile itemfile = ItemFile.make(); itemfile.type("full"); String filename = track.getChild("audio_file").getChildTextNN("file_name"); File f = new File(path + filename); if (f != null && f.exists()) { itemfile.setFile(f); //this will also set the filesize and calculate the checksums // set delivered path to file itemfile.setLocation(FileLocation.make(filename, filename)); } else { //file does not exist -> so we have to set the values "manually" //-> use filename as location itemfile.setLocation(FileLocation.make(filename, filename)); //file size if (track.getChild("audio_file").getChild("size") != null) { itemfile.bytes(Integer.parseInt(track.getChild("audio_file").getChildText("size"))); } // checksum md5 if (track.getChild("audio_file").getChild("checksum") != null) { Element cs = track.getChild("audio_file").getChild("checksum"); if (cs != null) { if (cs.getAttribute("type").equals("md5")) { String sMd5 = cs.getText(); byte[] md5 = SecurityHelper.HexDecoder.decode(sMd5); itemfile.checksums(Checksums.make().md5(md5)); } } } } item.addFile(itemfile); } bundle.addItem(item); } feed.addBundle(bundle); } catch (Exception e) { e.printStackTrace(); ir.succeeded = false; ir.errorMessage = e.getMessage(); ir.exception = e; } return feed; } private HashMap<String, String> calculateDateMajorities(Iterator<Element> it) { HashMap<String, String> ret = new HashMap<String, String>(); HashMap<String, Integer> salesDates = new HashMap<String, Integer>(); // kay = date | value = count HashMap<String, Integer> streamingDates = new HashMap<String, Integer>(); // kay = date | value = count String majorSalesDate = null; int majorSalesCount = -1; String majorStreamDate = null; int majorStreamCount = -1; while (it.hasNext()) { Element e = it.next(); String salesDate = e.getChildTextNN("sales_start_date"); String streamDate = e.getChildTextNN("stream_start_date"); //count major sales & streaming date if (salesDate.length() > 0) { //sales if (salesDates.get(salesDate) == null) { //add salesDates.put(salesDate, 1); } else { //increment salesDates.put(salesDate, salesDates.get(salesDate) + 1); } } if (streamDate.length() > 0) { //stream if (streamingDates.get(streamDate) == null) { //add streamingDates.put(streamDate, 1); } else { //increment streamingDates.put(streamDate, streamingDates.get(streamDate) + 1); } } } Iterator<String> itSale = salesDates.keySet().iterator(); while (itSale.hasNext()) { String key = itSale.next(); int i = salesDates.get(key); if (i > majorSalesCount) { majorSalesCount = i; majorSalesDate = key; } } Iterator<String> itStream = streamingDates.keySet().iterator(); while (itStream.hasNext()) { String key = itStream.next(); int i = streamingDates.get(key); if (i > majorStreamCount) { majorStreamCount = i; majorStreamDate = key; } } ret.put("stream", majorStreamDate); ret.put("sale", majorSalesDate); return ret; } /** * Checks if the trackTerritories are equal to those on bundle level. * * @param albumTerritories HashMap with all Territories on bundle leve. * @param trackTerritories Element with all Territories for the track. * * @return true if albumTerritories equal to trackTerritories */ private boolean asOnBundle(HashMap<String, Element> albumTerritories, Vector<Element> trackTerritories) { boolean ret = false; if (albumTerritories != null && trackTerritories != null && albumTerritories.size() == trackTerritories.size()) { ret = true; Iterator<Element> it = trackTerritories.iterator(); while (it.hasNext() && ret) { Element trackT = it.next(); Element albumT = albumTerritories.get(trackT.getChildTextNN("territory")); ret = (trackT.getChildTextNN("cleared_for_sale").equals(albumT.getChildTextNN("cleared_for_sale")) && trackT.getChildTextNN("cleared_for_stream") .equals(albumT.getChildTextNN("cleared_for_stream"))); } } return ret; } public Feed getFormatedFeedFromImport() { return this.getImportFeed(); } public Result getIr() { return ir; } public void setIr(Result ir) { this.ir = ir; } /** * In case you need to import a "Pie" takedown XML, you can enforce it to act * like a regualr import XML. */ public void forceTakedownImport() { this.forceImport = true; } }