// PathVisio, // a tool for data visualization and analysis using Biological Pathways // Copyright 2006-2011 BiGCaT Bioinformatics // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package org.wikipathways.bots; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.pathvisio.core.debug.Logger; import org.pathvisio.wikipathways.webservice.WSCurationTag; import org.pathvisio.wikipathways.webservice.WSCurationTagHistory; import org.pathvisio.wikipathways.webservice.WSPathwayInfo; import org.wikipathways.client.WikiPathwaysCache; import org.wikipathways.client.WikiPathwaysClient; public abstract class Bot { public static final String PROP_WS_URL = "webservice-url"; public static final String PROP_CACHE = "cache-path"; public static final String PROP_USER = "user"; public static final String PROP_PASS = "pass"; private WikiPathwaysClient client; private WikiPathwaysCache cache; private String user; private String pass; public Bot(Properties props) throws BotException { try { //Create the client String urlStr = props.getProperty(PROP_WS_URL); if(urlStr != null) { client = new WikiPathwaysClient(new URL(urlStr)); } else { client = new WikiPathwaysClient(); } //Get the cache path String cacheStr = props.getProperty(PROP_CACHE); if(cacheStr == null) { throw new BotException("Property cache-path is missing"); } cache = new WikiPathwaysCache(client, new File(cacheStr)); //Login if possible user = props.getProperty(PROP_USER); pass = props.getProperty(PROP_PASS); if(user != null && pass != null) { client.login(user, pass); } } catch (Exception e) { if(e instanceof BotException) throw (BotException)e; else throw new BotException(e); } } public abstract BotReport createReport(Collection result); public abstract String getTagName(); protected abstract Result scanPathway(File pathwayFile) throws BotException; public Collection scan() throws BotException { try { getCache().update(); } catch(Exception e) { throw new BotException(e); } List reports = new ArrayList(); for(File f : getCache().getFiles()) { reports.add(scanPathway(f)); } return reports; } public void applyCurationTags(Collection results, BotReport report) throws BotException { if(user == null || pass == null) { Logger.log.trace("No user account"); return; } try { WSCurationTag[] allTags = client.getCurationTagsByName(getTagName()); Map tagsByPathway = new HashMap(); for(WSCurationTag t : allTags) { tagsByPathway.put(t.getPathway().getId(), t); } Set overrides = new HashSet(); int i = 0; int size = results.size(); for(Result r : results) { //Find an existing tag WSPathwayInfo pwi = r.getPathwayInfo(); Logger.log.info("Processing pathway " + pwi.getId() + ", "+ i++ + " out of " + size); String pwId = pwi.getId(); //First check if the existing tag is up-to-date WSCurationTag tag = tagsByPathway.get(pwId); if(r.shouldTag()) { //Add or update tag if(tag != null) { //We found an existing tag //See if it's up-to-date if(r.equalsTag(tag.getText())) { //No action needed Logger.log.info("Existing tag is up-to-date"); continue; } else { //Update needed Logger.log.info("Applying updated tag to " + pwId); client.saveCurationTag( pwId, getTagName(), r.getTagText() ); } } else { //No existing tag //See if it was removed by a user String oldtext = checkRemoved(r); if(oldtext != null) { //See if the measured values have changed after the //user removed the tag if(!r.equalsTag(oldtext)) { //Tag has changed, so re-apply Logger.log.info("Re-applying tag to " + pwId); client.saveCurationTag( pwId, getTagName(),r.getTagText() ); } else { //Mark the pathway as overridden overrides.add(r.getPathwayInfo()); } } else { //No override, add the tag Logger.log.info("Applying new tag to " + pwId); client.saveCurationTag( pwId, getTagName(),r.getTagText() ); } } } else { //Remove tag if needed if(tag != null) { Logger.log.info("Removing tag from " + pwId); client.removeCurationTag(pwId, getTagName()); } } } StringBuilder strb = new StringBuilder(); for(WSPathwayInfo pwi : overrides) { strb.append("" + pwi.getId() + ", "); } if(strb.length() > 0) { report.setComment("User override tagging for pathways", strb.toString()); } } catch(Exception e) { throw new BotException(e); } } private String checkRemoved(Result r) throws BotException { try { WSCurationTagHistory[] hist = client.getCurationTagHistory(r.getPathwayInfo().getId()); //Find out if the tag was originally applied by this bot and then removed by a user for(WSCurationTagHistory h : hist) { if(user.equals(h.getUser())) { return null; //The current bot was the last one to touch the tag } else if("remove".equals(h.getAction())) { return h.getText(); //A user removed the tag } } return null; } catch(Exception e) { throw new BotException(e); } } protected WikiPathwaysClient getClient() { return client; } public WikiPathwaysCache getCache() { return cache; } abstract class Result { private WSPathwayInfo pathwayInfo; public Result(WSPathwayInfo pathwayInfo) { this.pathwayInfo = pathwayInfo; } public WSPathwayInfo getPathwayInfo() { return pathwayInfo; } /** * Check if the variables in the results equal * those in the tag text. */ public abstract boolean equalsTag(String tag); public abstract String getTagText(); public abstract boolean shouldTag(); } public static class BotException extends Exception { public BotException(Exception e) { super(e); } public BotException(String message) { super(message); } } public static void runAll(Bot bot, File htmlReport, File txtReport) throws BotException, IOException { Logger.log.trace("Running bot " + bot); Collection results = bot.scan(); Logger.log.trace("Generating report"); BotReport report = bot.createReport(results); Logger.log.trace("Applying curation tags"); bot.applyCurationTags(results, report); Logger.log.trace("Writing text report"); report.writeTextReport(txtReport); Logger.log.trace("Writing HTML report"); report.writeHtmlReport(htmlReport); } }