From c1aff0bc80c5a64ec93acd8b6c5844da2d6da509 Mon Sep 17 00:00:00 2001 From: jprocter Date: Sun, 4 Dec 2011 18:56:26 +0000 Subject: [PATCH] removed all dasobert code and begun to replace with Jdas calls. --- .classpath | 1 + lib/jdas-1.0.3.jar | Bin 0 -> 126580 bytes src/jalview/bin/Cache.java | 1 + src/jalview/gui/DasSourceBrowser.java | 131 +++-- .../biojava/dasobert/das/DAS_FeatureRetrieve.java | 287 ----------- .../biojava/dasobert/das/DAS_Feature_Handler.java | 314 ------------ .../biojava/dasobert/das/DAS_Sequence_Handler.java | 161 ------ src/org/biojava/dasobert/das/FeatureThread.java | 198 -------- src/org/biojava/dasobert/das/SequenceThread.java | 299 ----------- src/org/biojava/dasobert/das2/Das2Capability.java | 51 -- .../biojava/dasobert/das2/Das2CapabilityImpl.java | 131 ----- src/org/biojava/dasobert/das2/Das2Source.java | 42 -- src/org/biojava/dasobert/das2/Das2SourceImpl.java | 157 ------ .../biojava/dasobert/das2/DasSourceConverter.java | 92 ---- .../dasobert/das2/io/DAS2SourceHandler.java | 216 -------- .../biojava/dasobert/das2/io/DasSourceReader.java | 33 -- .../dasobert/das2/io/DasSourceReaderImpl.java | 183 ------- .../biojava/dasobert/dasregistry/Das1Source.java | 305 ------------ .../dasobert/dasregistry/Das2Validator.java | 44 -- .../dasregistry/DasCoordSysComparator.java | 128 ----- .../dasobert/dasregistry/DasCoordinateSystem.java | 233 --------- .../biojava/dasobert/dasregistry/DasSource.java | 130 ----- .../dasobert/dasregistry/DasSourceComparator.java | 190 ------- .../dasobert/eventmodel/AbstractDasEvent.java | 43 -- .../biojava/dasobert/eventmodel/FeatureEvent.java | 96 ---- .../dasobert/eventmodel/FeatureListener.java | 48 -- .../dasobert/eventmodel/ObjectListener.java | 51 -- .../biojava/dasobert/eventmodel/SequenceEvent.java | 62 --- .../dasobert/eventmodel/SequenceListener.java | 64 --- .../dasobert/feature/AbstractFeatureTrack.java | 278 ----------- .../biojava/dasobert/feature/AbstractSegment.java | 256 ---------- .../dasobert/feature/FeatureComparator.java | 87 ---- .../dasobert/feature/FeatureMapComparator.java | 68 --- src/org/biojava/dasobert/feature/FeatureTrack.java | 127 ----- .../dasobert/feature/FeatureTrackConverter.java | 526 -------------------- .../biojava/dasobert/feature/FeatureTrackImpl.java | 68 --- .../biojava/dasobert/feature/HistogramFeature.java | 95 ---- .../biojava/dasobert/feature/HistogramSegment.java | 67 --- src/org/biojava/dasobert/feature/Segment.java | 84 ---- .../dasobert/feature/SegmentComparator.java | 45 -- src/org/biojava/dasobert/feature/SegmentImpl.java | 83 --- 41 files changed, 105 insertions(+), 5370 deletions(-) create mode 100644 lib/jdas-1.0.3.jar delete mode 100755 src/org/biojava/dasobert/das/DAS_FeatureRetrieve.java delete mode 100755 src/org/biojava/dasobert/das/DAS_Feature_Handler.java delete mode 100755 src/org/biojava/dasobert/das/DAS_Sequence_Handler.java delete mode 100755 src/org/biojava/dasobert/das/FeatureThread.java delete mode 100755 src/org/biojava/dasobert/das/SequenceThread.java delete mode 100755 src/org/biojava/dasobert/das2/Das2Capability.java delete mode 100755 src/org/biojava/dasobert/das2/Das2CapabilityImpl.java delete mode 100755 src/org/biojava/dasobert/das2/Das2Source.java delete mode 100755 src/org/biojava/dasobert/das2/Das2SourceImpl.java delete mode 100755 src/org/biojava/dasobert/das2/DasSourceConverter.java delete mode 100755 src/org/biojava/dasobert/das2/io/DAS2SourceHandler.java delete mode 100755 src/org/biojava/dasobert/das2/io/DasSourceReader.java delete mode 100755 src/org/biojava/dasobert/das2/io/DasSourceReaderImpl.java delete mode 100755 src/org/biojava/dasobert/dasregistry/Das1Source.java delete mode 100755 src/org/biojava/dasobert/dasregistry/Das2Validator.java delete mode 100755 src/org/biojava/dasobert/dasregistry/DasCoordSysComparator.java delete mode 100755 src/org/biojava/dasobert/dasregistry/DasCoordinateSystem.java delete mode 100755 src/org/biojava/dasobert/dasregistry/DasSource.java delete mode 100755 src/org/biojava/dasobert/dasregistry/DasSourceComparator.java delete mode 100644 src/org/biojava/dasobert/eventmodel/AbstractDasEvent.java delete mode 100755 src/org/biojava/dasobert/eventmodel/FeatureEvent.java delete mode 100755 src/org/biojava/dasobert/eventmodel/FeatureListener.java delete mode 100755 src/org/biojava/dasobert/eventmodel/ObjectListener.java delete mode 100755 src/org/biojava/dasobert/eventmodel/SequenceEvent.java delete mode 100755 src/org/biojava/dasobert/eventmodel/SequenceListener.java delete mode 100644 src/org/biojava/dasobert/feature/AbstractFeatureTrack.java delete mode 100644 src/org/biojava/dasobert/feature/AbstractSegment.java delete mode 100644 src/org/biojava/dasobert/feature/FeatureComparator.java delete mode 100644 src/org/biojava/dasobert/feature/FeatureMapComparator.java delete mode 100644 src/org/biojava/dasobert/feature/FeatureTrack.java delete mode 100644 src/org/biojava/dasobert/feature/FeatureTrackConverter.java delete mode 100644 src/org/biojava/dasobert/feature/FeatureTrackImpl.java delete mode 100644 src/org/biojava/dasobert/feature/HistogramFeature.java delete mode 100644 src/org/biojava/dasobert/feature/HistogramSegment.java delete mode 100644 src/org/biojava/dasobert/feature/Segment.java delete mode 100644 src/org/biojava/dasobert/feature/SegmentComparator.java delete mode 100644 src/org/biojava/dasobert/feature/SegmentImpl.java diff --git a/.classpath b/.classpath index 01cf242..4e2109f 100644 --- a/.classpath +++ b/.classpath @@ -40,6 +40,7 @@ + diff --git a/lib/jdas-1.0.3.jar b/lib/jdas-1.0.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..6cc4e91ee2d2e4d6e3c422201fe05f47ab97aae8 GIT binary patch literal 126580 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%0AT$; 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 authority = new Vector(); + Vector type = new Vector(); + Vector label = new Vector(); + Vector taxIds=new Vector(); + authority.add("Any"); + type.add("Any"); + label.add("Any"); + for (int i = 0; i < sources.length; i++) { - DasSource ds = sources[i]; - - DasCoordinateSystem[] dcs = ds.getCoordinateSystem(); - - for (int j = 0; j < dcs.length; j++) + SOURCE ds = sources[i]; + VERSION latest=null; + for (VERSION v:ds.getVERSION()) { + if (latest==null || isLaterThan(latest.getCreated(),v.getCreated())) + { + // TODO: das 1.6 - should just get the first version - ignore other versions since not specified how to construct URL from version's URI + source URI + latest=v; + } + } + + for (COORDINATES cs: latest.getCOORDINATES()) { - if (!type.contains(dcs[j].getCategory())) + if (!type.contains(cs.getSource())) { - type.addElement(dcs[j].getCategory()); + type.add(cs.getSource()); // source==category } - if (!authority.contains(dcs[j].getName())) + if (!authority.contains(cs.getAuthority())) { - authority.addElement(dcs[j].getName()); + authority.add(cs.getAuthority()); } } - String[] slabels = ds.getLabels(); - for (int s = 0; s < slabels.length; s++) + for (PROP slabel:latest.getPROP()) { - if (!label.contains(slabels[s])) + if (slabel.getName().equalsIgnoreCase("LABEL") && !label.contains(slabel.getValue())) { - label.addElement(slabels[s]); + label.add(slabel.getValue()); } } @@ -412,6 +462,7 @@ public class DasSourceBrowser extends GDasSourceBrowser implements filter1.setListData(authority); filter2.setListData(type); filter3.setListData(label); + // filter4 taxIds javax.swing.SwingUtilities.invokeLater(new Runnable() { @@ -432,9 +483,8 @@ public class DasSourceBrowser extends GDasSourceBrowser implements { int selectedRow = table.getSelectionModel().getMinSelectionIndex(); nickname = table.getValueAt(selectedRow, 0).toString(); - url = ((DasSource) localSources.get(nickname)).getUrl(); - seqsrc = ((DasSource) localSources.get(nickname)) - .hasCapability("sequence"); + url = ((SOURCE) localSources.get(nickname)).getUri(); + seqsrc = ((SOURCE) localSources.get(nickname)).getVERSION().get(0).getCAPABILITY().contains(Capabilities.SEQUENCE); } JTextField nametf = new JTextField(nickname, 40); @@ -466,7 +516,32 @@ public class DasSourceBrowser extends GDasSourceBrowser implements urltf.setText(urltf.getText() + "/"); } - Das1Source local = new Das1Source(); + // build using pattern from test: sourcesclientImplTest + { + SOURCE source = new SOURCE(); + String uri = "http://das.sanger.ac.uk/das/dummysource"; + source.setUri("http://das.sanger.ac.uk/das/dummysource"); + source.setDescription("Dummy Test Source, should not be in a working registry sources doc"); + VERSION version = new VERSION(); + version.setUri(uri); + COORDINATES coord = new COORDINATES(); + coord.setAuthority("NCBI"); + coord.setSource("Chromosome"); + coord.setTaxid("9606"); + coord.setVersion("35"); + version.getCOORDINATES().add(coord); + CAPABILITY cap = new CAPABILITY(); + cap.setQueryUri(uri + "features"); + cap.setType("das1:" + Capabilities.FEATURES.getName()); + version.getCAPABILITY().add(cap); + source.getVERSION().add(version); + MAINTAINER m = new MAINTAINER(); + m.setEmail("jw12@sanger.ac.uk"); + source.setMAINTAINER(m); + source.setTitle("dummy title"); + + } + SOURCE local = new Das1Source(); local.setUrl(urltf.getText()); local.setNickname(nametf.getText()); diff --git a/src/org/biojava/dasobert/das/DAS_FeatureRetrieve.java b/src/org/biojava/dasobert/das/DAS_FeatureRetrieve.java deleted file mode 100755 index 7d35dea..0000000 --- a/src/org/biojava/dasobert/das/DAS_FeatureRetrieve.java +++ /dev/null @@ -1,287 +0,0 @@ -/** - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 19.03.2004 - * @author Andreas Prlic - * - */ -package org.biojava.dasobert.das; - -import java.io.*; -import java.lang.reflect.*; -import java.net.*; -import java.util.*; -import java.util.logging.*; -import javax.xml.parsers.*; - -import org.xml.sax.*; - -/** - * A class to perform a DAS features request - * - * @author Andreas Prlic Adapted for jalview use. - * @author Andrew Waterhouse Updated to Das 1.53e feature spec. - * @author Jim Procter - */ -public class DAS_FeatureRetrieve -{ - String version; - - List features; - - Logger logger; - - int comeBackLater; - - URL url; - - /** - * @param url - * the URL the features should be downloaded from - * - */ - public DAS_FeatureRetrieve(URL url) - { - super(); - - logger = Logger.getLogger("org.biojava.spice"); - features = new ArrayList(); - comeBackLater = -1; - this.url = url; - reload(); - } - - /** - * contact the DAS-feature server again. Usually it is not necessary to call - * this again, because the constructor already does, but if comeBackLater > -1 - * this should be called again. - * - */ - public void reload() - { - - try - { - - InputStream dasInStream = null; - try - { - dasInStream = open(url); - } catch (Exception e) - { - comeBackLater = -1; - System.out.println("NO RESPONSE FROM " + url); - logger.log(Level.FINE, "could not open connection to " + url, e); - return; - } - - SAXParserFactory spfactory = SAXParserFactory.newInstance(); - - spfactory.setValidating(false); - - SAXParser saxParser = null; - - try - { - saxParser = spfactory.newSAXParser(); - } catch (ParserConfigurationException e) - { - e.printStackTrace(); - } - - String vali = System.getProperty("XMLVALIDATION"); - - boolean validation = false; - if (vali != null) - { - if (vali.equals("true")) - { - validation = true; - } - } - - XMLReader xmlreader = saxParser.getXMLReader(); - - // XMLReader xmlreader = XMLReaderFactory.createXMLReader(); - try - { - xmlreader.setFeature("http://xml.org/sax/features/validation", - validation); - } catch (SAXException e) - { - logger.log(Level.FINE, "Cannot set validation " + validation); - } - - try - { - xmlreader - .setFeature( - "http://apache.org/xml/features/nonvalidating/load-external-dtd", - validation); - } catch (SAXNotRecognizedException e) - { - e.printStackTrace(); - logger - .log(Level.FINE, "Cannot set load-external-dtd " - + validation); - - } - - DAS_Feature_Handler cont_handle = new DAS_Feature_Handler(); - cont_handle.setDASCommand(url.toString()); - xmlreader.setContentHandler(cont_handle); - xmlreader.setErrorHandler(new org.xml.sax.helpers.DefaultHandler()); - InputSource insource = new InputSource(); - insource.setByteStream(dasInStream); - - try - { - xmlreader.parse(insource); - features = cont_handle.get_features(); - version = cont_handle.getVersion(); - - comeBackLater = cont_handle.getComBackLater(); - } catch (Exception e) - { - System.out - .println("Error parsing response from: " + url + "\n" + e); - logger.log(Level.FINE, "error while parsing response from " + url); - comeBackLater = -1; - features = new ArrayList(); - } - } catch (Exception ex) - { - ex.printStackTrace(); - comeBackLater = -1; - } - } - - /** - * open HttpURLConnection. Recommended way to open HttpURLConnections, since - * this take care of setting timeouts properly for java 1.4 and 1.5 - */ - public static HttpURLConnection openHttpURLConnection(URL url) - throws IOException, ConnectException - { - HttpURLConnection huc = null; - huc = (HttpURLConnection) url.openConnection(); - - String os_name = java.lang.System.getProperty("os.name"); - String os_version = java.lang.System.getProperty("os.version"); - String os_arch = java.lang.System.getProperty("os.arch"); - String VERSION = "1.0"; - - String userAgent = "Jalview " + VERSION + "(" + os_name + "; " - + os_arch + " ; " + os_version + ")"; - // e.g. "Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.7.2) Gecko/20040803" - huc.addRequestProperty("User-Agent", userAgent); - // logger.finest("opening "+url); - - int timeout = 10000; - System - .setProperty("sun.net.client.defaultConnectTimeout", timeout - + ""); - System.setProperty("sun.net.client.defaultReadTimeout", timeout + ""); - - // use reflection to determine if get and set timeout methods for - // urlconnection are available - // seems java 1.5 does not watch the System properties any longer... - // and java 1.4 did not provide these... - // for 1.4 see setSystemProperties - - try - { - // try to use reflection to set timeout property - Class urlconnectionClass = Class - .forName("java.net.HttpURLConnection"); - - Method setconnecttimeout = urlconnectionClass.getMethod( - "setConnectTimeout", new Class[] - { int.class }); - setconnecttimeout.invoke(huc, new Object[] - { new Integer(timeout) }); - - Method setreadtimeout = urlconnectionClass.getMethod( - "setReadTimeout", new Class[] - { int.class }); - setreadtimeout.invoke(huc, new Object[] - { new Integer(timeout) }); - // System.out.println("successfully set java 1.5 timeout"); - } catch (Exception e) - { - // e.printStackTrace(); - // most likely it was a NoSuchMEthodException and we are running java 1.4. - } - return huc; - } - - private InputStream open(URL url) throws java.io.IOException, - java.net.ConnectException - { - InputStream inStream = null; - - HttpURLConnection huc = openHttpURLConnection(url); - - inStream = huc.getInputStream(); - - return inStream; - - } - - /** - * returns a List of Features - * - * @return a List of Maps containing the features - */ - public List get_features() - { - - return features; - } - - /** - * Get the version string of the reference object. If it does not match the - * version string that is obtained from the reference server there is a - * version problem! - * - * @return version string. (e.g. a MD5 digest of the reference sequence) - */ - public String getVersion() - { - return version; - } - - public void setVersion(String version) - { - this.version = version; - } - - /** - * returns the comeBackLater value - if a server returned suchh - - * - * @return comeBackLater in seconds, or -1 if not provided by server - */ - public int getComeBackLater() - { - - return comeBackLater; - - } - -} diff --git a/src/org/biojava/dasobert/das/DAS_Feature_Handler.java b/src/org/biojava/dasobert/das/DAS_Feature_Handler.java deleted file mode 100755 index b6badc7..0000000 --- a/src/org/biojava/dasobert/das/DAS_Feature_Handler.java +++ /dev/null @@ -1,314 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 19.03.2004 - * @author Andreas Prlic - * - */ -package org.biojava.dasobert.das; - -import java.util.*; - -import org.xml.sax.*; -import org.xml.sax.helpers.*; - -/** - * a class to parse the response of a DAS - Feature request - * - * @author Andreas Prlic Adapted for jalview use. - * @author Andrew Waterhouse Updated to Das 1.53e feature spec. - * @author Jim Procter - * - */ -public class DAS_Feature_Handler extends DefaultHandler -{ - - /** - * - */ - List features; - - boolean first_flag; - - HashMap feature; - - String featurefield; - - StringBuffer characterdata; - - String dasCommand; - - int comeBackLater; - - int maxFeatures; - - String segmentId; - - String version; - - String type_id; - - String type_category; - - public DAS_Feature_Handler() - { - super(); - - features = new ArrayList(); - first_flag = true; - featurefield = ""; - characterdata = new StringBuffer(); - dasCommand = ""; - comeBackLater = -1; - maxFeatures = -1; - segmentId = ""; - version = ""; - type_id = ""; - type_category = ""; - } - - /** - * get the id information specified int the SEGMENT field of the DAS response - * - * @return the segmentId or an emtpy string if not available - */ - public String getSegmentId() - { - return segmentId; - } - - /** - * get the version informationspecified in the SEGMENT field of the DAS - * response - * - * @return the version information of an empty string if not available - */ - public String getVersion() - { - return version; - } - - public boolean isMD5Checksum() - { - - if ((version != null) && (version.length() == 32)) - return true; - return false; - } - - /** - * specifies a maximum number of features to be downloaded. if a server - * returns more, they will be ignored. default is to load all features - * - * @param max - * the maximium number of features to be downloaded - */ - - public void setMaxFeatures(int max) - { - maxFeatures = max; - } - - public int getMaxFeatures() - { - return maxFeatures; - } - - public void setDASCommand(String cmd) - { - dasCommand = cmd; - } - - public String getDASCommand() - { - return dasCommand; - } - - public List get_features() - { - return features; - } - - public int getComBackLater() - { - return comeBackLater; - } - - void start_feature(String uri, String name, String qName, Attributes atts) - { - - if ((maxFeatures > 0) && (features.size() > maxFeatures)) - { - characterdata = new StringBuffer(); - return; - } - feature = new HashMap(); - String id = atts.getValue("id"); - feature.put("id", id); - feature.put("dassource", dasCommand); - characterdata = new StringBuffer(); - } - - void add_featuredata(String uri, String name, String qName) - { - // System.out.println("featurefield "+featurefield+ " data "+characterdata); - // NOTE can have multiple lines .. - - if ((maxFeatures > 0) && (features.size() > maxFeatures)) - { - return; - } - - String data = (String) feature.get(featurefield); - String featureText = characterdata.toString(); - if (data != null) - { - featureText = data + " " + featureText; - } - - if (qName.equals("TYPE")) - { - if (featureText.length() < 1) - featureText = type_id; - - feature.put("TYPE_ID", type_id); - feature.put("TYPE_CATEGORY", type_category); - type_id = ""; - type_category = ""; - } - - feature.put(featurefield, featureText); - featurefield = ""; - characterdata = new StringBuffer(); - } - - private void addLink(String uri, String name, String qName, - Attributes atts) - { - String href = atts.getValue("href"); - feature.put("LINK", href); - characterdata = new StringBuffer(); - featurefield = "LINK-TEXT"; - - } - - private void addGroup(String uri, String name, String qName, - Attributes atts) - { - String id = atts.getValue("id"); - feature.put("GROUP", id); - characterdata = new StringBuffer(); - featurefield = "GROUP"; - } - - public void startElement(String uri, String name, String qName, - Attributes atts) - { - // System.out.println("new element "+qName); - - if (qName.equals("FEATURE")) - { - start_feature(uri, name, qName, atts); - } - else if (qName.equals("LINK")) - { - addLink(uri, name, qName, atts); - } - else if (qName.equals("GROUP")) - { - addGroup(uri, name, qName, atts); - } - else if (qName.equals("METHOD") || qName.equals("TYPE") - || qName.equals("START") || qName.equals("END") - || qName.equals("NOTE") || qName.equals("SCORE") - || qName.equals("ORIENTATION")) - { - characterdata = new StringBuffer(); - featurefield = qName; - } - else if (qName.equals("SEGMENT")) - { - String id = atts.getValue("id"); - if (id != null) - segmentId = id; - String v = atts.getValue("version"); - if (v != null) - version = v; - - } - if (qName.equals("TYPE")) - { - type_id = atts.getValue("id"); - type_category = atts.getValue("category"); - } - - } - - public void startDocument() - { - } - - public void endDocument() - { - } - - public void endElement(String uri, String name, String qName) - { - - if (qName.equals("METHOD") || qName.equals("TYPE") - || qName.equals("START") || qName.equals("END") - || qName.equals("NOTE") || qName.equals("LINK") - || qName.equals("SCORE") || qName.equals("ORIENTATION") - || qName.equals("GROUP")) - { - add_featuredata(uri, name, qName); - } - else if (qName.equals("FEATURE")) - { - - if (maxFeatures > 0) - { - if (features.size() < maxFeatures) - { - features.add(feature); - } - } - else - { - // no restriction - features.add(feature); - } - } - } - - public void characters(char ch[], int start, int length) - { - if (maxFeatures > 0) - if (features.size() > maxFeatures) - return; - - for (int i = start; i < start + length; i++) - { - - characterdata.append(ch[i]); - } - - } - -} diff --git a/src/org/biojava/dasobert/das/DAS_Sequence_Handler.java b/src/org/biojava/dasobert/das/DAS_Sequence_Handler.java deleted file mode 100755 index fe5be8b..0000000 --- a/src/org/biojava/dasobert/das/DAS_Sequence_Handler.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 19.03.2004 - * @author Andreas Prlic - * - */ -package org.biojava.dasobert.das; - -import org.xml.sax.helpers.DefaultHandler; -import org.xml.sax.Attributes; -import java.util.logging.*; - -/** - * a class that parses the XML response of a DAS - sequence command. - * - * @author Andreas Prlic - * - */ -public class DAS_Sequence_Handler extends DefaultHandler -{ - - StringBuffer sequence; - - int length; - - int maxLength; - - String version; - - boolean dna_flag; - - /** - * - */ - public DAS_Sequence_Handler() - { - super(); - - sequence = new StringBuffer(); - length = 0; - dna_flag = false; - maxLength = -1; - version = ""; - } - - /** - * set a maximum length of sequence that should be loaded default: -1. if -1 - * no length restriction is being supplied - * - * @return the maximum length or -1 if no restriction - */ - public int getMaxLength() - { - return maxLength; - } - - /** - * set a maximum length of sequence that should be loaded default: -1. if -1 - * no length restriction is being supplied - * - * @param maxLength - * the maximum length or -1 if unrestricted - */ - public void setMaxLength(int maxLength) - { - this.maxLength = maxLength; - } - - public void startElement(String uri, String name, String qName, - Attributes atts) - { - - if (qName.equals("SEQUENCE")) - { - version = atts.getValue("version"); - String lenstr = atts.getValue("stop"); - length = Integer.parseInt(lenstr); - dna_flag = true; - } - - } - - public void characters(char ch[], int start, int length) - { - - if (maxLength > 0) - if (sequence.length() > maxLength) - return; - - if (dna_flag) - for (int i = start; i < start + length; i++) - { - - // all sorts of characters can be found in "seqeunces" ... ignore - // them... - switch (ch[i]) - { - case '\\': - // System.out.print("\\\\"); - break; - case '"': - // System.out.print("\\\""); - break; - case '\n': - // System.out.print("\\n"); - break; - case '\r': - // System.out.print("\\r"); - break; - case '\t': - // System.out.print("\\t"); - break; - case ' ': - break; - default: - sequence = sequence.append(ch[i]); - - break; - } - } - - } - - public String get_sequence() - { - - if (maxLength < 0) - { - if (length != sequence.length()) - { - Logger logger = Logger.getLogger("org.biojava.spice"); - logger.warning("Sequence does not match specified length!"); - } - } - - return sequence.toString(); - } - - public String getVersion() - { - return version; - } - -} diff --git a/src/org/biojava/dasobert/das/FeatureThread.java b/src/org/biojava/dasobert/das/FeatureThread.java deleted file mode 100755 index 172078b..0000000 --- a/src/org/biojava/dasobert/das/FeatureThread.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 21.09.2004 - * @author Andreas Prlic - * - */ - -package org.biojava.dasobert.das; - -import java.net.*; -import java.util.*; -import java.util.logging.*; - -import org.biojava.dasobert.dasregistry.*; -import org.biojava.dasobert.eventmodel.*; - -/** - * a thread that connects to a DAS - Feature service and gets the features - * - * @author Andreas Prlic - */ - -public class FeatureThread implements Runnable -{ - - /** - * number of times the client tries to reconnect to the server if a "come back - * later" is returned. the server should provide a reasonable estimation how - * long it will take him to create results. if this number of requests is - * still not successfull, give up. - */ - public static int MAX_COME_BACK_ITERATIONS = 5; - - public static int MAX_NR_FEATURES = 300; - - static Logger logger = Logger.getLogger("org.biojava.spice"); - - Das1Source dasSource; - - String ac; - - List featureListeners; - - Thread thread; - - public FeatureThread(String accessionCode, Das1Source dasSource) - { - this.dasSource = dasSource; - this.ac = accessionCode; - featureListeners = new ArrayList(); - } - - public void addFeatureListener(FeatureListener li) - { - featureListeners.add(li); - } - - public void clearFeatureListeners() - { - featureListeners.clear(); - } - - public synchronized void stop() - { - thread = null; - notify(); - } - - public void run() - { - Thread me = Thread.currentThread(); - while (thread == me) - { - String url = dasSource.getUrl(); - String queryString = url + "features?segment=" + ac; - URL cmd = null; - try - { - cmd = new URL(queryString); - } catch (MalformedURLException e) - { - logger.warning("got MalformedURL from das source " + dasSource); - e.printStackTrace(); - - } - - logger.info("requesting features from " + cmd); - DAS_FeatureRetrieve ftmp = new DAS_FeatureRetrieve(cmd); - - int comeBackLater = ftmp.getComeBackLater(); - int securityCounter = 0; - while ((thread == me) && (comeBackLater > 0)) - { - securityCounter++; - if (securityCounter >= MAX_COME_BACK_ITERATIONS) - { - comeBackLater = -1; - break; - - } - notifyComeBackLater(comeBackLater); - // server is still calculating - asks us to come back later - try - { - wait(comeBackLater); - } catch (InterruptedException e) - { - comeBackLater = -1; - break; - } - - ftmp.reload(); - comeBackLater = ftmp.getComeBackLater(); - } - - if (!(thread == me)) - { - break; - } - - List features = ftmp.get_features(); - String version = ftmp.getVersion(); - - // a fallback mechanism to prevent DAS sources from bringing down spice - if (features.size() > MAX_NR_FEATURES) - { - logger - .warning("DAS source returned more than " + MAX_NR_FEATURES - + "features. " - + " throwing away excess features at " + cmd); - features = features.subList(0, MAX_NR_FEATURES); - } - - // notify FeatureListeners - Map[] feats = (Map[]) features.toArray(new Map[features.size()]); - notifyFeatureListeners(feats, version); - - break; - - } - thread = null; - - } - - public void start() - { - thread = new Thread(this); - thread.start(); - } - - private void notifyFeatureListeners(Map[] feats, String version) - { - logger.finest("FeatureThread found " + feats.length + " features"); - FeatureEvent fevent = new FeatureEvent(feats, dasSource, version); - Iterator fiter = featureListeners.iterator(); - while (fiter.hasNext()) - { - FeatureListener fi = (FeatureListener) fiter.next(); - fi.newFeatures(fevent); - } - } - - /** - * the Annotation server requested to be queried again in a while - * - * @param comeBackLater - */ - private void notifyComeBackLater(int comeBackLater) - { - FeatureEvent event = new FeatureEvent(new HashMap[0], dasSource, ""); - event.setComeBackLater(comeBackLater); - Iterator fiter = featureListeners.iterator(); - while (fiter.hasNext()) - { - FeatureListener fi = (FeatureListener) fiter.next(); - fi.comeBackLater(event); - } - - } - -} diff --git a/src/org/biojava/dasobert/das/SequenceThread.java b/src/org/biojava/dasobert/das/SequenceThread.java deleted file mode 100755 index 720c60b..0000000 --- a/src/org/biojava/dasobert/das/SequenceThread.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Nov 20, 2005 - * - */ -package org.biojava.dasobert.das; - -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Iterator; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.biojava.dasobert.dasregistry.Das1Source; -import org.biojava.dasobert.eventmodel.SequenceEvent; -import org.biojava.dasobert.eventmodel.SequenceListener; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXNotRecognizedException; -import org.xml.sax.XMLReader; -import java.util.*; - -/** - * a thread that gets the sequence from a DAS server - * - * @author Andreas Prlic - * - */ -public class SequenceThread extends Thread -{ - - Das1Source[] sequenceServers; - - String sp_accession; - - List seqListeners; - - String version; - - static Logger logger = Logger.getLogger("org.biojava.spice"); - - public SequenceThread(String sp_accession, Das1Source ds) - { - super(); - Das1Source[] dss = new Das1Source[1]; - dss[0] = ds; - this.sp_accession = sp_accession; - this.sequenceServers = dss; - clearSequenceListeners(); - version = ""; - } - - public SequenceThread(String sp_accession, Das1Source[] ds) - { - super(); - - this.sp_accession = sp_accession; - this.sequenceServers = ds; - clearSequenceListeners(); - } - - public void clearSequenceListeners() - { - seqListeners = new ArrayList(); - } - - public void addSequenceListener(SequenceListener lis) - { - seqListeners.add(lis); - } - - public void run() - { - getSequence(); - } - - public void getSequence() - { - - boolean gotSequence = false; - - for (int i = 0; i < sequenceServers.length; i++) - { - - if (gotSequence) - break; - - Das1Source ds = sequenceServers[i]; - String url = ds.getUrl(); - char lastChar = url.charAt(url.length() - 1); - if (!(lastChar == '/')) - url += "/"; - String dascmd = url + "sequence?segment="; - String connstr = dascmd + sp_accession; - - try - { - version = ""; - - String sequence = retrieveSequence(connstr); - // TODO: discriminate exceptions caused by connection/server errors and ones caused by the sequence not being found in the reference source. - if (sequence!=null) - { - // bug in aristotle das source? - sequence.replaceAll(" ", ""); - gotSequence = true; - // set the sequence ... - - triggerNewSequence(sp_accession, sequence, ds, version); - } - return; - } catch (Exception ex) - { - ex.printStackTrace(); - logger.warning(ex.getMessage()); - - // triggerException(ex); - - } - } - - logger - .log( - Level.WARNING, - "could not retreive UniProt sequence from any available DAS sequence server"); - - triggerNoSequence(sp_accession); - - } - - // private void triggerException(Exception e){ - // Iterator iter = seqListeners.iterator(); - // while (iter.hasNext()){ - // SequenceListener li = (SequenceListener)iter.next(); - // li.exceptionOccured(e); - // } - // } - - private void triggerNewSequence(String sp_accession, String sequence, - Das1Source source, String version) - { - - Iterator iter = seqListeners.iterator(); - while (iter.hasNext()) - { - SequenceListener li = (SequenceListener) iter.next(); - // SequenceEvent event = new SequenceEvent(sequence); - SequenceEvent event = new SequenceEvent(sp_accession, sequence, - version); - event.setSource(source); - li.newSequence(event); - } - } - - private void triggerNoSequence(String ac) - { - - Iterator iter = seqListeners.iterator(); - while (iter.hasNext()) - { - SequenceListener li = (SequenceListener) iter.next(); - li.noObjectFound(ac); - } - - } - - /** - * retrieve the Sequence from a DAS server. - * - * @param connstr - - * the DAS - request string. e.g. - * http://www.ebi.ac.uk/das-srv/uniprot/das/aristotle/sequence?segment=P00280 - * @return the requested Sequence - * @throws Exception - */ - public String retrieveSequence(String connstr) throws Exception - { - - // logger.finest("trying: " + connstr) ; - URL dasUrl = new URL(connstr); - // DAS_httpConnector dhtp = new DAS_httpConnector() ; - logger.info("requesting sequence from " + connstr); - InputStream dasInStream = open(dasUrl); - - SAXParserFactory spfactory = SAXParserFactory.newInstance(); - - // never do this - // String vali = System.getProperty("XMLVALIDATION"); - String vali = "false"; - boolean validate = false; - if ((vali != null) && (vali.equals("true"))) - validate = true; - spfactory.setValidating(validate); - - SAXParser saxParser = null; - - try - { - saxParser = spfactory.newSAXParser(); - } catch (ParserConfigurationException e) - { - // e.printStackTrace(); - logger.log(Level.FINER, "Uncaught exception", e); - } - - XMLReader xmlreader = saxParser.getXMLReader(); - - try - { - xmlreader.setFeature("http://xml.org/sax/features/validation", - validate); - } catch (SAXException e) - { - logger.finer("Cannot set validation to " + validate); - logger.log(Level.FINER, "Uncaught exception", e); - } - - try - { - xmlreader - .setFeature( - "http://apache.org/xml/features/nonvalidating/load-external-dtd", - validate); - } catch (SAXNotRecognizedException e) - { - // e.printStackTrace(); - logger.finer("Cannot set load-external-dtd to" + validate); - logger.log(Level.FINER, "Uncaught exception", e); - // System.err.println("Cannot set load-external-dtd to" + validate); - } - if (dasInStream==null) - { - return null; - } - // DAS_DNA_Handler cont_handle = new DAS_DNA_Handler() ; - DAS_Sequence_Handler cont_handle = new DAS_Sequence_Handler(); - xmlreader.setContentHandler(cont_handle); - xmlreader.setErrorHandler(new org.xml.sax.helpers.DefaultHandler()); - InputSource insource = new InputSource(); - insource.setByteStream(dasInStream); - - xmlreader.parse(insource); - String sequence = cont_handle.get_sequence(); - version = cont_handle.getVersion(); - // logger.finest("Got sequence from DAS: " +sequence); - - logger.exiting(this.getClass().getName(), "retreiveSequence", sequence); - return sequence; - } - - private InputStream open(URL url) - { - { - - InputStream inStream = null; - try - { - - HttpURLConnection huc = null; - - huc = DAS_FeatureRetrieve.openHttpURLConnection(url); - - logger.finest(huc.getResponseMessage()); - - inStream = huc.getInputStream(); - - } catch (Exception ex) - { - ex.printStackTrace(); - logger.log(Level.WARNING, "exception occured", ex); - } - - return inStream; - } - - } - -} diff --git a/src/org/biojava/dasobert/das2/Das2Capability.java b/src/org/biojava/dasobert/das2/Das2Capability.java deleted file mode 100755 index e91bc77..0000000 --- a/src/org/biojava/dasobert/das2/Das2Capability.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 9, 2006 - * - */ -package org.biojava.dasobert.das2; - -public interface Das2Capability -{ - - public boolean equals(Das2Capability other); - - public int hashCode(); - - public void setCapability(String type); - - public String getCapability(); - - public void setQueryUri(String id); - - public String getQueryUri(); - - public void setFormats(String[] formats); - - public String[] getFormats(); - - /** - * checks if this capability is actually of das1 style - * - * @return boolean true if the capability is in DAS1 style - */ - public boolean isDas1Style(); - -} diff --git a/src/org/biojava/dasobert/das2/Das2CapabilityImpl.java b/src/org/biojava/dasobert/das2/Das2CapabilityImpl.java deleted file mode 100755 index 196b681..0000000 --- a/src/org/biojava/dasobert/das2/Das2CapabilityImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 9, 2006 - * - */ -package org.biojava.dasobert.das2; - -public class Das2CapabilityImpl implements Das2Capability -{ - - String capability; - - String[] formats; - - String queryId; - - public static String DAS1_CAPABILITY_PREFIX = "das1:"; - - public Das2CapabilityImpl() - { - super(); - capability = "undef"; - queryId = ""; - formats = new String[0]; - - } - - public boolean isDas1Style() - { - - if (capability == null) - { - return false; - } - if (capability.length() < DAS1_CAPABILITY_PREFIX.length()) - { - return false; - } - if (capability.substring(0, DAS1_CAPABILITY_PREFIX.length()).equals( - DAS1_CAPABILITY_PREFIX)) - { - return true; - } - return false; - - } - - public boolean equals(Das2Capability other) - { - - boolean status = true; - - if (!capability.equals(other.getCapability())) - { - status = false; - } - if (!queryId.equals(other.getQueryUri())) - { - status = false; - } - - return status; - } - - public int hashCode() - { - int h = 7; - h = 31 * h + (null == capability ? 0 : capability.hashCode()); - h = 31 * h + (null == queryId ? 0 : queryId.hashCode()); - - return h; - } - - public String toString() - { - String txt = "capability " + capability + " queryId " + queryId; - return txt; - } - - public String getCapability() - { - - return capability; - } - - public String[] getFormats() - { - return formats; - } - - public String getQueryUri() - { - return queryId; - } - - public void setCapability(String type) - { - capability = type; - - } - - public void setFormats(String[] formats) - { - - this.formats = formats; - } - - public void setQueryUri(String id) - { - queryId = id; - - } - -} diff --git a/src/org/biojava/dasobert/das2/Das2Source.java b/src/org/biojava/dasobert/das2/Das2Source.java deleted file mode 100755 index 71d59e0..0000000 --- a/src/org/biojava/dasobert/das2/Das2Source.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 9, 2006 - * - */ -package org.biojava.dasobert.das2; - -import org.biojava.dasobert.dasregistry.*; - -public interface Das2Source extends DasSource -{ - - public Das2Capability[] getDas2Capabilities(); - - public void setDas2Capabilities(Das2Capability[] capabilities); - - /** - * test if this is a DAS1 source represented as a DAS2 source if true - this - * source can be converted into a DAS1 source by using - * DasSourceConverter.toDas1(Das2Source); - * - * @return true if the DasSource has DAS1 capabilties - */ - public boolean hasDas1Capabilities(); -} diff --git a/src/org/biojava/dasobert/das2/Das2SourceImpl.java b/src/org/biojava/dasobert/das2/Das2SourceImpl.java deleted file mode 100755 index 2f5a7ed..0000000 --- a/src/org/biojava/dasobert/das2/Das2SourceImpl.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 9, 2006 - * - */ -package org.biojava.dasobert.das2; - -import org.biojava.dasobert.dasregistry.*; - -public class Das2SourceImpl extends Das1Source implements Das2Source - -{ - - Das2Capability[] capabilities; - - public Das2SourceImpl() - { - super(); - - capabilities = new Das2Capability[0]; - } - - /** - * compare if two DasSources are identical - * - */ - public boolean equals(DasSource other) - { - - if (this == other) - { - return true; - } - - if ((other == null) || (other.getClass() != this.getClass())) - { - return false; - } - - // to compare if two Das2Sources are identical we do the following: - // we check the capabilities - - Das2SourceImpl d2o = (Das2SourceImpl) other; - - if (nickname.equals(d2o.getNickname())) - { - return true; - } - - Das2Capability[] othercaps = d2o.getDas2Capabilities(); - - if (!(capabilities.length == othercaps.length)) - { - return false; - } - - for (int x = 0; x < capabilities.length; x++) - { - Das2Capability tmpcap = capabilities[x]; - boolean foundCap = false; - for (int y = 0; y < othercaps.length; y++) - { - Das2Capability tmpcapo = othercaps[y]; - if (tmpcap.equals(tmpcapo)) - { - foundCap = true; - } - } - if (!foundCap) - { - return false; - } - } - - // TODO? - // should we add a check for coordinate systems? - // but we already check for the endpoints, that should be enough... - - return true; - - } - - public int hashCode() - { - int h = 7; - - h = 31 * h + (null == nickname ? 0 : nickname.hashCode()); - - for (int x = 0; x < capabilities.length; x++) - { - Das2Capability cap = capabilities[x]; - h = 31 * h + cap.hashCode(); - } - - return h; - } - - public boolean hasDas1Capabilities() - { - - // test if any of the capabilities is a das1 capabilitiy - - for (int i = 0; i < capabilities.length; i++) - { - Das2Capability cap = capabilities[i]; - if (cap.isDas1Style()) - { - return true; - } - } - return false; - - } - - public String[] getCapabilities() - { - // todo mark as not needed / not appropriate ... - return super.getCapabilities(); - } - - public void setCapabilities(String[] u) - { - // TODO Auto-generated method stub - super.setCapabilities(u); - } - - public Das2Capability[] getDas2Capabilities() - { - // TODO Auto-generated method stub - return capabilities; - } - - public void setDas2Capabilities(Das2Capability[] capabilities) - { - // TODO Auto-generated method stub - this.capabilities = capabilities; - - } - -} diff --git a/src/org/biojava/dasobert/das2/DasSourceConverter.java b/src/org/biojava/dasobert/das2/DasSourceConverter.java deleted file mode 100755 index 3e4d8e8..0000000 --- a/src/org/biojava/dasobert/das2/DasSourceConverter.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Mar 23, 2006 - * - */ -package org.biojava.dasobert.das2; - -// import org.biojava.bio.program.das.dasalignment.DASException; -import org.biojava.dasobert.dasregistry.*; - -public class DasSourceConverter -{ - - public DasSourceConverter() - { - super(); - - } - - /** - * convert a das2 source to a das 1 source. This only will work if is passes - * the Das2Source.isDas1Source() test i.e. this is really a das1 server there - * - * @param das2source - * a DAS2Source to be converted - * @return a Das1Source - * @throws DASException - */ - public static Das1Source toDas1Source(Das2Source das2source) - throws Exception - { - if (!das2source.hasDas1Capabilities()) - { - throw new Exception( - "this das source does not have das1 capabilitites"); - } - - Das1Source ds = new Das1Source(); - ds.setAdminemail(das2source.getAdminemail()); - ds.setDescription(das2source.getDescription()); - ds.setHelperurl(das2source.getHelperurl()); - ds.setRegisterDate(das2source.getRegisterDate()); - ds.setLeaseDate(das2source.getLeaseDate()); - ds.setLabels(das2source.getLabels()); - ds.setCoordinateSystem(das2source.getCoordinateSystem()); - ds.setNickname(das2source.getNickname()); - ds.setId(das2source.getId()); - ds.setLabels(das2source.getLabels()); - - // convert the capabilitites to das1 capabiltities and get the url - Das2Capability[] caps = das2source.getDas2Capabilities(); - String[] das1capabilitites = new String[caps.length]; - int DASPREFIXLENGTH = Das2CapabilityImpl.DAS1_CAPABILITY_PREFIX - .length(); - - for (int i = 0; i < caps.length; i++) - { - Das2Capability cap = caps[i]; - - String c = cap.getCapability(); - - das1capabilitites[i] = c.substring(DASPREFIXLENGTH, c.length()); - - String query_uri = cap.getQueryUri(); - - String url = query_uri.substring(0, - (query_uri.length() - c.length() + DASPREFIXLENGTH)); - ds.setUrl(url); - } - ds.setCapabilities(das1capabilitites); - - return ds; - } - -} diff --git a/src/org/biojava/dasobert/das2/io/DAS2SourceHandler.java b/src/org/biojava/dasobert/das2/io/DAS2SourceHandler.java deleted file mode 100755 index 0ee0b5e..0000000 --- a/src/org/biojava/dasobert/das2/io/DAS2SourceHandler.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Mar 15, 2006 - * - */ -package org.biojava.dasobert.das2.io; - -import java.util.*; - -import org.biojava.dasobert.das2.*; -import org.biojava.dasobert.dasregistry.*; -import org.xml.sax.*; -import org.xml.sax.helpers.*; - -/** - * a parser for the DAS2 sources response - * - * @author Andreas Prlic - * @since 6:53:45 PM - * @version %I% %G% - */ -public class DAS2SourceHandler extends DefaultHandler -{ - - List sources; - - Das2Source currentSource; - - List coordinates; - - List capabilities; - - List labels; - - public static final String LABELPROPERTY = "label"; - - public DAS2SourceHandler() - { - super(); - - sources = new ArrayList(); - currentSource = new Das2SourceImpl(); - coordinates = new ArrayList(); - capabilities = new ArrayList(); - labels = new ArrayList(); - } - - private void startSource(String uri, String name, String qName, - Attributes atts) - { - - String id = atts.getValue("uri"); - String title = atts.getValue("title"); - String doc_ref = atts.getValue("doc_href"); - String description = atts.getValue("description"); - - currentSource.setId(id); - currentSource.setNickname(title); - currentSource.setHelperurl(doc_ref); - currentSource.setDescription(description); - - } - - private DasCoordinateSystem getCoordinateSystem(String uri, String name, - String qname, Attributes atts) - { - // e.g. uri="http://das.sanger.ac.uk/dasregistry/coordsys/CS_LOCAL6" - // source="Protein Sequence" authority="UniProt" test_range="P06213" /> - DasCoordinateSystem dcs = new DasCoordinateSystem(); - String id = atts.getValue("uri"); - dcs.setUniqueId(id); - - String source = atts.getValue("source"); - dcs.setCategory(source); - - String authority = atts.getValue("authority"); - dcs.setName(authority); - - String test_range = atts.getValue("test_range"); - dcs.setTestCode(test_range); - - try - { - String taxidstr = atts.getValue("taxid"); - int taxid = Integer.parseInt(taxidstr); - dcs.setNCBITaxId(taxid); - } catch (Exception e) - { - } - - String version = atts.getValue("version"); - if (version != null) - { - dcs.setVersion(version); - } - - return dcs; - } - - public void startElement(String uri, String name, String qName, - Attributes atts) - { - // System.out.println("new element "+qName); - - if (qName.equals("SOURCE")) - { - // System.out.println("new Source " + atts.getValue(uri)); - currentSource = new Das2SourceImpl(); - coordinates = new ArrayList(); - capabilities = new ArrayList(); - - startSource(uri, name, qName, atts); - - } - else if (qName.equals("MAINTAINER")) - { - String email = atts.getValue("email"); - currentSource.setAdminemail(email); - } - else if (qName.equals("COORDINATES")) - { - DasCoordinateSystem dcs = getCoordinateSystem(uri, name, qName, atts); - coordinates.add(dcs); - - } - else if (qName.equals("CAPABILITY")) - { - Das2Capability cap = getCapability(uri, name, qName, atts); - capabilities.add(cap); - } - else if (qName.equals("PROPERTY")) - { - addProperty(uri, name, qName, atts); - } - } - - private Das2Capability getCapability(String uri, String name, - String qName, Attributes atts) - { - // e.g - Das2Capability cap = new Das2CapabilityImpl(); - - String type = atts.getValue("type"); - cap.setCapability(type); - String query_uri = atts.getValue("query_uri"); - cap.setQueryUri(query_uri); - return cap; - - } - - private void addProperty(String uri, String name, String qName, - Attributes atts) - { - String pname = atts.getValue("name"); - String label = atts.getValue("value"); - if (pname.equals(LABELPROPERTY)) - { - labels.add(label); - } - } - - public void startDocument() - { - sources = new ArrayList(); - coordinates = new ArrayList(); - capabilities = new ArrayList(); - } - - public void endElement(String uri, String name, String qName) - { - if (qName.equals("SOURCE")) - { - currentSource.setDas2Capabilities((Das2Capability[]) capabilities - .toArray(new Das2Capability[capabilities.size()])); - // System.out.println("got coordinates " + coordinates.size()); - currentSource.setCoordinateSystem((DasCoordinateSystem[]) coordinates - .toArray(new DasCoordinateSystem[coordinates.size()])); - - currentSource.setLabels((String[]) labels.toArray(new String[labels - .size()])); - labels.clear(); - - // System.out.println("Das2SourceHandler endElement name " + name + " uri - // " + uri + " qName " + qName); - // System.out.println("Das2SourceHandler adding to source: " + - // currentSource.getId()); - sources.add(currentSource); - currentSource = new Das2SourceImpl(); - } - } - - public DasSource[] getSources() - { - // System.out.println("Das2SourceHandler: source size: " + sources.size()); - return (DasSource[]) sources.toArray(new DasSource[sources.size()]); - } - -} diff --git a/src/org/biojava/dasobert/das2/io/DasSourceReader.java b/src/org/biojava/dasobert/das2/io/DasSourceReader.java deleted file mode 100755 index 62a28f6..0000000 --- a/src/org/biojava/dasobert/das2/io/DasSourceReader.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 24, 2006 - * - */ -package org.biojava.dasobert.das2.io; - -import java.io.*; - -import org.biojava.dasobert.dasregistry.*; - -public interface DasSourceReader -{ - - public DasSource[] readDasSource(InputStream stream); -} diff --git a/src/org/biojava/dasobert/das2/io/DasSourceReaderImpl.java b/src/org/biojava/dasobert/das2/io/DasSourceReaderImpl.java deleted file mode 100755 index 54afa25..0000000 --- a/src/org/biojava/dasobert/das2/io/DasSourceReaderImpl.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 24, 2006 - * - */ -package org.biojava.dasobert.das2.io; - -import java.io.*; -import java.net.*; -import javax.xml.parsers.*; - -import org.biojava.dasobert.das.*; -import org.biojava.dasobert.dasregistry.*; -import org.xml.sax.*; - -public class DasSourceReaderImpl implements DasSourceReader -{ - - Exception loggedException; - - public DasSourceReaderImpl() - { - super(); - loggedException = null; - - // open the stream to a server and then parse the result ... - } - - private InputStream open(URL url) throws java.io.IOException, - java.net.ConnectException - { - InputStream inStream = null; - - HttpURLConnection huc = DAS_FeatureRetrieve.openHttpURLConnection(url); - - inStream = huc.getInputStream(); - - return inStream; - - } - - public DasSource[] readDasSource(URL url) - { - DasSource[] sources = new DasSource[0]; - - try - { - InputStream stream = open(url); - - sources = readDasSource(stream); - } catch (Exception e) - { - System.err.println("Exception for url:"+url); - e.printStackTrace(); - loggedException = e; - } - return sources; - } - - /** - * read a DAS2 sources response and return a list of DAS sources. - * - */ - public DasSource[] readDasSource(InputStream stream) - { - - DasSource[] sources = new DasSource[0]; - - try - { - SAXParserFactory spfactory = SAXParserFactory.newInstance(); - - spfactory.setValidating(false); - - SAXParser saxParser = null; - - try - { - saxParser = spfactory.newSAXParser(); - } catch (ParserConfigurationException e) - { - e.printStackTrace(); - loggedException = e; - } - - String vali = System.getProperty("XMLVALIDATION"); - - boolean validation = false; - if (vali != null) - { - if (vali.equals("true")) - { - validation = true; - } - } - - XMLReader xmlreader = saxParser.getXMLReader(); - - // XMLReader xmlreader = XMLReaderFactory.createXMLReader(); - try - { - xmlreader.setFeature("http://xml.org/sax/features/validation", - validation); - } catch (SAXException e) - { - // logger.log(Level.FINE,"Cannot set validation " + validation); - } - - try - { - xmlreader - .setFeature( - "http://apache.org/xml/features/nonvalidating/load-external-dtd", - validation); - } catch (SAXNotRecognizedException e) - { - e.printStackTrace(); - // logger.log(Level.FINE,"Cannot set load-external-dtd "+validation); - - } - - DAS2SourceHandler cont_handle = new DAS2SourceHandler(); - - xmlreader.setContentHandler(cont_handle); - xmlreader.setErrorHandler(new org.xml.sax.helpers.DefaultHandler()); - InputSource insource = new InputSource(); - insource.setByteStream(stream); - - xmlreader.parse(insource); - sources = cont_handle.getSources(); - - } catch (Exception e) - { - e.printStackTrace(); - loggedException = e; - } - return sources; - } - - public Exception getLoggedException() - { - return loggedException; - } - - public static void main(String[] args) - { - String url = "http://www.spice-3d.org/dasregistry/das2/sources/"; - DasSourceReaderImpl reader = new DasSourceReaderImpl(); - try - { - URL u = new URL(url); - DasSource[] sources = reader.readDasSource(u); - for (int i = 0; i < sources.length; i++) - { - DasSource ds = sources[i]; - System.out.println(ds.toString()); - } - - } catch (Exception e) - { - e.printStackTrace(); - } - - } - -} diff --git a/src/org/biojava/dasobert/dasregistry/Das1Source.java b/src/org/biojava/dasobert/dasregistry/Das1Source.java deleted file mode 100755 index c46d709..0000000 --- a/src/org/biojava/dasobert/dasregistry/Das1Source.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 15.04.2004 - * @author Andreas Prlic - * - */ -package org.biojava.dasobert.dasregistry; - -import java.util.*; - -// import org.biojava.dasobert.das2.io.DasSourceWriter; -// import org.biojava.dasobert.das2.io.DasSourceWriterImpl; -// import org.biojava.utils.xml.PrettyXMLWriter; - -/** - * a simple Bean class to be returned via SOAP - * - * @author Andreas Prlic - */ - -public class Das1Source implements DasSource -{ - String url; - - protected String nickname; - - String adminemail; - - String description; - - DasCoordinateSystem[] coordinateSystem; - - String[] capabilities; - - String[] labels; - - String helperurl; - - Date registerDate; - - Date leaseDate; - - String id; - - boolean local; - - Map properties; - - boolean alertAdmin; - - public static String EMPTY_ID = "UNK:-1"; - - public Das1Source() - { - id = EMPTY_ID; - url = ""; - adminemail = ""; - description = ""; - // String empty = "" ; - nickname = ""; - coordinateSystem = new DasCoordinateSystem[0]; - // coordinateSystem[0] = new DasCoordinateSystem(); - capabilities = new String[0]; - labels = new String[0]; - // capabilities[0] = empty ; - registerDate = new Date(); - leaseDate = new Date(); - helperurl = ""; - local = true; - } - - public boolean equals(DasSource other) - { - System.out.println("Das1Source equals, comparing with other DasSource"); - if (!(other instanceof Das1Source)) - { - return false; - } - - Das1Source ods = (Das1Source) other; - - if (ods.getUrl().equals(url)) - { - return true; - } - if (ods.getNickname().equals(nickname)) - { - return true; - } - return false; - } - - public int hashCode() - { - int h = 7; - - h = 31 * h + (null == nickname ? 0 : nickname.hashCode()); - h = 31 * h + (null == url ? 0 : url.hashCode()); - - return h; - } - - /** - * the DAS2 string representation of this DAS source - * - * public String toString() { - * - * StringWriter writer = new StringWriter(); - * - * PrintWriter pw = new PrintWriter(writer); PrettyXMLWriter xw = new - * PrettyXMLWriter(pw); - * - * DasSourceWriter dswriter = new DasSourceWriterImpl(); try { - * dswriter.writeDasSource(xw,this); } catch (IOException e){ - * e.printStackTrace(); } - * - * return writer.toString(); - * } - */ - public void setLocal(boolean flag) - { - local = flag; - } - - public boolean isLocal() - { - return local; - } - - public void setId(String i) - { - id = i; - } - - /** - * get a the Id of the DasSource. The Id is a unique db identifier. The public - * DAS-Registry has Auto_Ids that look like DASSOURCE:12345; public look like - * XYZ:12345, where the XYZ prefix can be configured in the config file. - */ - public String getId() - { - return id; - } - - public void setNickname(String name) - { - nickname = name; - } - - public String getNickname() - { - return nickname; - } - - public void setUrl(String u) - { - char lastChar = u.charAt(u.length() - 1); - if (lastChar != '/') - { - u += "/"; - } - - url = u; - } - - public void setAdminemail(String u) - { - adminemail = u; - } - - public void setDescription(String u) - { - description = u; - } - - public void setCoordinateSystem(DasCoordinateSystem[] u) - { - coordinateSystem = u; - } - - public void setCapabilities(String[] u) - { - capabilities = u; - } - - public String getUrl() - { - return url; - } - - public String getAdminemail() - { - return adminemail; - } - - public String getDescription() - { - return description; - } - - public String[] getCapabilities() - { - return capabilities; - } - - /** - * test if a this source has a particular capability - * - * @param testCapability - * @return true if the server has this capability. - */ - public boolean hasCapability(String testCapability) - { - for (int i = 0; i < capabilities.length; i++) - { - String cap = capabilities[i]; - if (cap.equals(testCapability)) - return true; - } - return false; - } - - public DasCoordinateSystem[] getCoordinateSystem() - { - return coordinateSystem; - } - - public void setRegisterDate(Date d) - { - registerDate = d; - } - - public Date getRegisterDate() - { - return registerDate; - } - - public void setLeaseDate(Date d) - { - leaseDate = d; - } - - public Date getLeaseDate() - { - return leaseDate; - } - - public void setLabels(String[] ls) - { - labels = ls; - } - - public String[] getLabels() - { - return labels; - } - - public void setHelperurl(String url) - { - helperurl = url; - } - - public String getHelperurl() - { - return helperurl; - } - - public void setAlertAdmin(boolean flag) - { - alertAdmin = flag; - } - - public boolean getAlertAdmin() - { - return alertAdmin; - } - - public Map getProperties() - { - return properties; - } - - public void setProperties(Map properties) - { - this.properties = properties; - } - -} diff --git a/src/org/biojava/dasobert/dasregistry/Das2Validator.java b/src/org/biojava/dasobert/dasregistry/Das2Validator.java deleted file mode 100755 index fea8a0f..0000000 --- a/src/org/biojava/dasobert/dasregistry/Das2Validator.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Mar 20, 2006 - * - */ -package org.biojava.dasobert.dasregistry; - -import org.biojava.dasobert.das2.*; - -public class Das2Validator -{ - - public Das2Validator() - { - super(); - - } - - public boolean validate(Das2Source ds) - { - - // TODO this bit still needs to be implemented! - - return true; - } - -} diff --git a/src/org/biojava/dasobert/dasregistry/DasCoordSysComparator.java b/src/org/biojava/dasobert/dasregistry/DasCoordSysComparator.java deleted file mode 100755 index dbae74d..0000000 --- a/src/org/biojava/dasobert/dasregistry/DasCoordSysComparator.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 15.04.2004 - * @author Andreas Prlic - * - */ - -package org.biojava.dasobert.dasregistry; - -import java.util.*; - -/** - * a comparator to sort DasSources - * - * @author Andreas Prlic - */ - -public abstract class DasCoordSysComparator implements Comparator -{ - - private final String name; - - private static final Map COMPS_BY_NAME; - - public DasCoordSysComparator(String str) - { - // System.out.println("new dasSourceComparator " + str); - name = str; - } - - public static final Comparator BY_NAME = new DasCoordSysComparator("name") - { - protected Comparable getField(DasCoordinateSystem ds) - { - return ds.getName(); - } - }; - - public static final Comparator BY_ID = new DasCoordSysComparator("id") - { - protected Comparable getField(DasCoordinateSystem ds) - { - return ds.getUniqueId(); - } - }; - - public static final Comparator BY_CATEGORY = new DasCoordSysComparator( - "category") - { - protected Comparable getField(DasCoordinateSystem ds) - { - return ds.getCategory(); - } - }; - - public static final Comparator BY_ORGANISM = new DasCoordSysComparator( - "organism") - { - protected Comparable getField(DasCoordinateSystem ds) - { - return ds.getOrganismName(); - } - }; - - public static final Comparator BY_TAXID = new DasCoordSysComparator( - "taxid") - { - protected Comparable getField(DasCoordinateSystem ds) - { - return ds.getNCBITaxId() + ""; - } - }; - - static - { - COMPS_BY_NAME = new HashMap(); - COMPS_BY_NAME.put(BY_ID.toString(), BY_ID); - COMPS_BY_NAME.put(BY_NAME.toString(), BY_NAME); - COMPS_BY_NAME.put(BY_CATEGORY.toString(), BY_CATEGORY); - COMPS_BY_NAME.put(BY_ORGANISM.toString(), BY_ORGANISM); - COMPS_BY_NAME.put(BY_TAXID.toString(), BY_TAXID); - } - - public static Comparator fromString(String name) - { - if (COMPS_BY_NAME.containsKey(name)) - { - return (Comparator) COMPS_BY_NAME.get(name); - } - else - { - throw new IllegalArgumentException("Can't compare by key " + name); - } - } - - protected abstract Comparable getField(DasCoordinateSystem ds); - - /** compare two DasCoordSys objects */ - public int compare(Object a, Object b) - { - DasCoordinateSystem x = (DasCoordinateSystem) a; - DasCoordinateSystem y = (DasCoordinateSystem) b; - return getField(x).compareTo(getField(y)); - } - - public String toString() - { - return name; - } - -} diff --git a/src/org/biojava/dasobert/dasregistry/DasCoordinateSystem.java b/src/org/biojava/dasobert/dasregistry/DasCoordinateSystem.java deleted file mode 100755 index 8936a16..0000000 --- a/src/org/biojava/dasobert/dasregistry/DasCoordinateSystem.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 15.04.2004 - * @author Andreas Prlic - * - */ -package org.biojava.dasobert.dasregistry; - -/** - * a Bean to be returned via SOAP. It takes care of the DAS - coordinate Systems - * - * @author Andreas Prlic - */ -public class DasCoordinateSystem -{ - - String name; - - String category; - - String organism_name; - - int ncbi_tax_id; - - String uniqueId; - - String version; - - String testCode; - - public DasCoordinateSystem() - { - uniqueId = ""; - name = ""; - category = ""; - organism_name = ""; - ncbi_tax_id = 0; - version = ""; - testCode = ""; - } - - public boolean equals(DasCoordinateSystem other) - { - boolean match = true; - System.out.println("comparing " + this.toString() + " to " - + other.toString()); - // URI has piority - if ((!uniqueId.equals("")) && (uniqueId.equals(other.getUniqueId()))) - { - return true; - } - - if (ncbi_tax_id != other.getNCBITaxId()) - { - System.out.println("mismatch in ncbi tax id " + ncbi_tax_id + " != " - + other.getNCBITaxId()); - match = false; - } - if (!version.equals(other.getVersion())) - { - System.out.println("mismatch in version"); - match = false; - } - if (!category.equals(other.getCategory())) - { - System.out.println("mismatch in category"); - match = false; - } - if (!name.equals(other.getName())) - { - System.out.println("mismatch in name"); - match = false; - } - System.out.println(" match: " + match); - - return match; - } - - public int hashCode() - { - int h = 7; - - h = 31 * h + (null == name ? 0 : name.hashCode()); - h = 31 * h + (null == category ? 0 : category.hashCode()); - - return h; - } - - public Object clone() - { - DasCoordinateSystem d = new DasCoordinateSystem(); - d.setTestCode(testCode); - d.setCategory(category); - d.setName(name); - d.setNCBITaxId(ncbi_tax_id); - d.setUniqueId(getUniqueId()); - d.setOrganismName(getOrganismName()); - d.setVersion(getVersion()); - return d; - } - - public String getTestCode() - { - return testCode; - } - - public void setTestCode(String testCode) - { - if (testCode == null) - { - testCode = ""; - } - this.testCode = testCode; - } - - public void setUniqueId(String id) - { - uniqueId = id; - } - - public String getUniqueId() - { - return uniqueId; - } - - public void setName(String n) - { - name = n; - } - - public String getName() - { - return name; - } - - public void setCategory(String c) - { - category = c; - } - - public String getCategory() - { - return category; - } - - public void setOrganismName(String t) - { - organism_name = t; - } - - public String getOrganismName() - { - return organism_name; - } - - public void setNCBITaxId(int id) - { - ncbi_tax_id = id; - } - - public int getNCBITaxId() - { - return ncbi_tax_id; - } - - public String getVersion() - { - return version; - } - - public void setVersion(String version) - { - if (version == null) - { - version = ""; - } - this.version = version; - } - - public String toString() - { - String nam = name; - if (!version.equals("")) - { - nam += "_" + version; - } - - if (organism_name.equals("")) - { - return nam + "," + category; - } - else - { - return nam + "," + category + "," + organism_name; - } - } - - public static DasCoordinateSystem fromString(String rawString) - { - String[] spl = rawString.split(","); - DasCoordinateSystem dcs = new DasCoordinateSystem(); - if (spl.length == 2) - { - dcs.setName(spl[0]); - dcs.setCategory(spl[1]); - } - if (spl.length == 3) - { - dcs.setName(spl[0]); - dcs.setCategory(spl[1]); - dcs.setOrganismName(spl[2]); - } - return dcs; - } - -} diff --git a/src/org/biojava/dasobert/dasregistry/DasSource.java b/src/org/biojava/dasobert/dasregistry/DasSource.java deleted file mode 100755 index 892963b..0000000 --- a/src/org/biojava/dasobert/dasregistry/DasSource.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 8, 2006 - * - */ -package org.biojava.dasobert.dasregistry; - -import java.util.*; - -public interface DasSource -{ - - public void setLocal(boolean flag); - - public boolean isLocal(); - - /** - * compare if two das sources are equal - * - * @param ds - * @return returns true if two DAS sources are equivalent - */ - public boolean equals(DasSource ds); - - /** - * classes that implement equals, should also implement hashKey - * - * @return the hash code of a das source - */ - public int hashCode(); - - public void setId(String i); - - /** - * get a the Id of the DasSource. The Id is a unique db identifier. The public - * DAS-Registry has Auto_Ids that look like DASSOURCE:12345; public look like - * XYZ:12345, where the XYZ prefix can be configured in the config file. - * - * @return String the ID of a Das Source - */ - public String getId(); - - public void setNickname(String name); - - public String getNickname(); - - public void setUrl(String u); - - public void setAdminemail(String u); - - public void setDescription(String u); - - public void setCoordinateSystem(DasCoordinateSystem[] u); - - public void setCapabilities(String[] u); - - /** - * test if a this source has a particular capability - * - * @param testCapability - * @return true if the server has this capability. - */ - public boolean hasCapability(String testCapability); - - public String getUrl(); - - public String getAdminemail(); - - public String getDescription(); - - public String[] getCapabilities(); - - public DasCoordinateSystem[] getCoordinateSystem(); - - public void setRegisterDate(Date d); - - public Date getRegisterDate(); - - public void setLeaseDate(Date d); - - public Date getLeaseDate(); - - public void setLabels(String[] ls); - - public String[] getLabels(); - - public void setHelperurl(String url); - - public String getHelperurl(); - - // TestCode is now part of the coordinate system! - // public void setTestCode(String code); - // public String getTestCode(); - - public void setAlertAdmin(boolean flag); - - public boolean getAlertAdmin(); - - /** - * set Properties for this DAS source, e.g. project name - * - * @param properties - */ - public void setProperties(Map properties); - - /** - * get Properties for this DAS source - * - * @return Properties - */ - public Map getProperties(); - -} \ No newline at end of file diff --git a/src/org/biojava/dasobert/dasregistry/DasSourceComparator.java b/src/org/biojava/dasobert/dasregistry/DasSourceComparator.java deleted file mode 100755 index 0d52fd9..0000000 --- a/src/org/biojava/dasobert/dasregistry/DasSourceComparator.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 15.04.2004 - * @author Andreas Prlic - * - */ - -package org.biojava.dasobert.dasregistry; - -import java.util.*; - -/** - * a comparator to sort DasSources - * - * @author Andreas Prlic, Thomas Down - */ - -public abstract class DasSourceComparator implements Comparator -{ - - private final String name; - - private static final Map COMPS_BY_NAME; - - private static final int TWODAYS = 1000 * 60 * 60 * 24 * 2; - - public DasSourceComparator(String str) - { - // System.out.println("new dasSourceComparator " + str); - name = str; - } - - public static final Comparator BY_ID = new DasSourceComparator("id") - { - protected Comparable getField(DasSource ds) - { - return ds.getId(); - } - }; - - public static final Comparator BY_NICKNAME = new DasSourceComparator( - "nickname") - { - protected Comparable getField(DasSource ds) - { - return ds.getNickname(); - } - }; - - public static final Comparator BY_STATUS = new DasSourceComparator( - "status") - { - protected Comparable getField(DasSource ds) - { - - Date now = new Date(); - - if (ds.getLeaseDate().getTime() < (now.getTime() - TWODAYS)) - return new Integer(0); - return new Integer(1); - } - }; - - public static final Comparator BY_REGISTER_DATE = new DasSourceComparator( - "registerdate") - { - protected Comparable getField(DasSource ds) - { - return ds.getRegisterDate(); - } - }; - - public static final Comparator BY_LEASE_DATE = new DasSourceComparator( - "leasedate") - { - protected Comparable getField(DasSource ds) - { - return ds.getLeaseDate(); - } - }; - - public static final Comparator BY_URL = new DasSourceComparator("url") - { - protected Comparable getField(DasSource ds) - { - return ds.getUrl(); - } - }; - - public static final Comparator BY_ADMIN_EMAIL = new DasSourceComparator( - "adminemail") - { - protected Comparable getField(DasSource ds) - { - return ds.getAdminemail(); - } - }; - - public static final Comparator BY_DESCRIPTION = new DasSourceComparator( - "description") - { - protected Comparable getField(DasSource ds) - { - return ds.getDescription(); - } - }; - - public static final Comparator BY_CAPABILITIES = new DasSourceComparator( - "capabilities") - { - protected Comparable getField(DasSource ds) - { - String[] caps = ds.getCapabilities(); - return caps.length == 0 ? "" : caps[0]; - } - }; - - public static final Comparator BY_COORDINATE_SYSTEM = new DasSourceComparator( - "coordinateSystem") - { - protected Comparable getField(DasSource ds) - { - DasCoordinateSystem[] dcss = ds.getCoordinateSystem(); - return dcss.length == 0 ? "" : dcss[0].toString(); - } - }; - - static - { - COMPS_BY_NAME = new HashMap(); - COMPS_BY_NAME.put(BY_ID.toString(), BY_ID); - COMPS_BY_NAME.put(BY_NICKNAME.toString(), BY_NICKNAME); - COMPS_BY_NAME.put(BY_REGISTER_DATE.toString(), BY_REGISTER_DATE); - COMPS_BY_NAME.put(BY_LEASE_DATE.toString(), BY_LEASE_DATE); - COMPS_BY_NAME.put(BY_URL.toString(), BY_URL); - COMPS_BY_NAME.put(BY_ADMIN_EMAIL.toString(), BY_ADMIN_EMAIL); - COMPS_BY_NAME.put(BY_DESCRIPTION.toString(), BY_DESCRIPTION); - COMPS_BY_NAME.put(BY_CAPABILITIES.toString(), BY_CAPABILITIES); - COMPS_BY_NAME - .put(BY_COORDINATE_SYSTEM.toString(), BY_COORDINATE_SYSTEM); - COMPS_BY_NAME.put(BY_STATUS.toString(), BY_STATUS); - - } - - public static Comparator fromString(String name) - { - if (COMPS_BY_NAME.containsKey(name)) - { - return (Comparator) COMPS_BY_NAME.get(name); - } - else - { - throw new IllegalArgumentException("Can't compare by key " + name); - } - } - - protected abstract Comparable getField(DasSource ds); - - /** compare two DasSource objects */ - public int compare(Object a, Object b) - { - - DasSource x = (DasSource) a; - DasSource y = (DasSource) b; - return getField(x).compareTo(getField(y)); - } - - public String toString() - { - return name; - } - -} diff --git a/src/org/biojava/dasobert/eventmodel/AbstractDasEvent.java b/src/org/biojava/dasobert/eventmodel/AbstractDasEvent.java deleted file mode 100644 index d8cbebe..0000000 --- a/src/org/biojava/dasobert/eventmodel/AbstractDasEvent.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Nov 17, 2006 - * - */ - -package org.biojava.dasobert.eventmodel; - -import org.biojava.dasobert.dasregistry.Das1Source; - -public class AbstractDasEvent -{ - - Das1Source dasSource; - - public Das1Source getSource() - { - return dasSource; - } - - public void setSource(Das1Source source) - { - this.dasSource = source; - } - -} diff --git a/src/org/biojava/dasobert/eventmodel/FeatureEvent.java b/src/org/biojava/dasobert/eventmodel/FeatureEvent.java deleted file mode 100755 index dd89ef3..0000000 --- a/src/org/biojava/dasobert/eventmodel/FeatureEvent.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Oct 28, 2005 - * - */ -package org.biojava.dasobert.eventmodel; - -import java.util.*; - -import org.biojava.dasobert.dasregistry.*; - -public class FeatureEvent extends AbstractDasEvent -{ - - Map[] features; - - int comeBackLater; - - String version; - - public FeatureEvent(Map[] features, Das1Source dasSource, String version) - { - super(); - this.features = features; - this.dasSource = dasSource; - comeBackLater = -1; - this.version = version; - } - - public int getComeBackLater() - { - return comeBackLater; - } - - public void setComeBackLater(int comeBackLater) - { - this.comeBackLater = comeBackLater; - } - - /** - * get the features that have been found. - * - * do something like Map[] features = event.getFeatures(); - * - *
-   * for (int i = 0; i < features; i++)
-   * {
-   *   Map f = features[i];
-   *   String type = (String) f.get("TYPE");
-   *   System.out.println(type);
-   * }
-   * 
- * - * @return a Map containng the features - */ - public Map[] getFeatures() - { - return features; - } - - /** - * Get the version of the reference object that has been annotated. Compare - * the version string with the version string obtained from the reference - * server. If they don;t match there is a version problem between the - * annotation and the reference! - * - * @return the version string (e.g. an MD5 digest of the reference sequence) - */ - public String getVersion() - { - return version; - } - - public void setVersion(String version) - { - this.version = version; - } - -} diff --git a/src/org/biojava/dasobert/eventmodel/FeatureListener.java b/src/org/biojava/dasobert/eventmodel/FeatureListener.java deleted file mode 100755 index 235c486..0000000 --- a/src/org/biojava/dasobert/eventmodel/FeatureListener.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Oct 28, 2005 - * - */ -package org.biojava.dasobert.eventmodel; - -// import org.biojava.spice.multipanel.eventmodel.FeatureEvent; - -/** - * a feature listener that returns the raw features as returned by a DAS source. - * - */ -public interface FeatureListener -{ - - /** - * new features have been returned from the Annotation server - * - * @param e - */ - public void newFeatures(FeatureEvent e); - - /** - * the server says that he is busy and we should try again in x seconds - * - * @param e - */ - public void comeBackLater(FeatureEvent e); - -} diff --git a/src/org/biojava/dasobert/eventmodel/ObjectListener.java b/src/org/biojava/dasobert/eventmodel/ObjectListener.java deleted file mode 100755 index a19ae4d..0000000 --- a/src/org/biojava/dasobert/eventmodel/ObjectListener.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Nov 1, 2005 - * - */ -package org.biojava.dasobert.eventmodel; - -/** - * an interface for the listeners of new PDB code requested / new Uniprot code - * requested - * - * @author Andreas Prlic - * - */ -public interface ObjectListener -{ - - /** - * a new object has been requested - * - * @param accessionCode - */ - public void newObjectRequested(String accessionCode); - - /** - * no object with that accessionCode has been found - * - * @param accessionCode - */ - public void noObjectFound(String accessionCode); - - // public void exceptionOccured(Exception e); - -} diff --git a/src/org/biojava/dasobert/eventmodel/SequenceEvent.java b/src/org/biojava/dasobert/eventmodel/SequenceEvent.java deleted file mode 100755 index 484cf49..0000000 --- a/src/org/biojava/dasobert/eventmodel/SequenceEvent.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Nov 20, 2005 - * - */ -package org.biojava.dasobert.eventmodel; - -public class SequenceEvent extends AbstractDasEvent -{ - - String sequence; - - String accessionCode; - - String version; - - public SequenceEvent(String accessionCode, String seq, String version) - { - super(); - sequence = seq; - this.accessionCode = accessionCode; - this.version = version; // bugfix here ? - } - - public String getAccessionCode() - { - return accessionCode; - } - - public String getSequence() - { - return sequence; - } - - public String getVersion() - { - return version; - } - - public void setVersion(String version) - { - this.version = version; - } - -} diff --git a/src/org/biojava/dasobert/eventmodel/SequenceListener.java b/src/org/biojava/dasobert/eventmodel/SequenceListener.java deleted file mode 100755 index df3a687..0000000 --- a/src/org/biojava/dasobert/eventmodel/SequenceListener.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Jun 10, 2005 - * - */ -package org.biojava.dasobert.eventmodel; - -/** - * An interface fore events related to selections of sequence position, sequence - * range and locking of the selection. - * - * @author Andreas Prlic - * - */ -public interface SequenceListener extends ObjectListener -{ - - /* select a certain sequence position */ - public void selectedSeqPosition(int position); - - /** - * select a certain range of a sequence - * - * @param start - * the start - * @param end - * the end of the range - */ - public void selectedSeqRange(int start, int end); - - /** - * the current selecetion is locked and can not be changed - * - * @param flag - * true if selection should be locked - */ - public void selectionLocked(boolean flag); - - public void newSequence(SequenceEvent e); - - /** - * clear what has been selected - * - * - */ - public void clearSelection(); -} diff --git a/src/org/biojava/dasobert/feature/AbstractFeatureTrack.java b/src/org/biojava/dasobert/feature/AbstractFeatureTrack.java deleted file mode 100644 index 0ad2df7..0000000 --- a/src/org/biojava/dasobert/feature/AbstractFeatureTrack.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 9, 2005 - * - */ -package org.biojava.dasobert.feature; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * An Abstract class representing a Feature as being diplayed in the - * SeqFeaturePanel A feature corresponds to everything that is visible in a - * "line" and can contain one or multiple Segments. - * - * - * @author Andreas Prlic - * - */ -public abstract class AbstractFeatureTrack implements FeatureTrack, - Cloneable -{ - - String name; - - String method; - - String type; - - List segments; - - String note; - - String link; - - String source; - - String score; - - String orientation; - - String typeID; - - String typeCategory; - - public AbstractFeatureTrack() - { - source = "Unknown"; - method = "Unknown"; - type = "Unknown"; - note = ""; - link = ""; - score = ""; - orientation = null; - segments = new ArrayList(); - - } - - public abstract Object clone(); - - public String toString() - { - String str = "Feature: method: " + method + " type: " + type; - if (name != null) - str += " name: " + name; - - if ((note != null) && (!note.equals("null"))) - { - if (note.length() > 40) - str += "note: " + note.substring(0, 39) + "..."; - else - str += " note: " + note; - } - str += " # segments: " + segments.size(); - return str; - } - - /** - * returns true if the specified sequence position is within the range of this - * Feature - * - * @param seqPosition - * the position to check - * @return true if the position is within the ranges of the segments of this - * feature - */ - public boolean overlaps(int seqPosition) - { - List segments = getSegments(); - Iterator iter = segments.iterator(); - - while (iter.hasNext()) - { - - Segment seg = (Segment) iter.next(); - if (seg.overlaps(seqPosition)) - return true; - } - - return false; - } - - public void setSource(String s) - { - source = s; - } - - public String getSource() - { - return source; - }; - - public void setName(String nam) - { - name = nam; - } - - public String getName() - { - return name; - } - - public void setMethod(String methd) - { - method = methd; - } - - public String getMethod() - { - return method; - } - - public void setType(String typ) - { - type = typ; - } - - public String getType() - { - return type; - } - - public void setNote(String nte) - { - if (nte != null) - note = nte; - } - - public String getNote() - { - return note; - } - - public void setLink(String lnk) - { - link = lnk; - } - - public String getLink() - { - return link; - } - - public void setScore(String s) - { - score = s; - } - - public String getScore() - { - return score; - } - - /** add a segment to this feature */ - public void addSegment(int start, int end, String name) - { - Segment s = new SegmentImpl(); - s.setStart(start); - s.setEnd(end); - s.setName(name); - s.setParent(this); - segments.add(s); - } - - public void addSegment(Segment s) - { - s.setParent(this); - segments.add(s); - } - - public List getSegments() - { - return segments; - } - - public String getOrientation() - { - return orientation; - } - - public void setOrientation(String orientation) - { - this.orientation = orientation; - } - - /** - * test if two features are equivalent important: only comares type,method and - * source. The individual segments are not compared! - * - */ - public boolean equals(FeatureTrack feat) - { - // if ( note == null) { - // if (( feat.getNote() == null ) || - // ( feat.getNote().equals(""))) { - // } else if ( this.note.equals(feat.getNote())){ - // return true; - // } - if (this.type.equals(feat.getType())) - { - if (this.method.equals(feat.getMethod())) - { - if (this.source.equals(feat.getSource())) - { - if (this.note.equals(feat.getNote())) - { - return true; - } - } - } - } - return false; - - } - - public String getTypeCategory() - { - // TODO Auto-generated method stub - return typeCategory; - } - - public String getTypeID() - { - // TODO Auto-generated method stub - return typeID; - } - - public void setTypeCategory(String typeCategory) - { - this.typeCategory = typeCategory; - - } - - public void setTypeID(String typeID) - { - this.typeID = typeID; - - } - -} diff --git a/src/org/biojava/dasobert/feature/AbstractSegment.java b/src/org/biojava/dasobert/feature/AbstractSegment.java deleted file mode 100644 index 12c5e1d..0000000 --- a/src/org/biojava/dasobert/feature/AbstractSegment.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on May 22, 2007 - * - */ - -package org.biojava.dasobert.feature; - -import java.awt.Color; - -public abstract class AbstractSegment implements Segment, Cloneable -{ - int start; - - int end; - - String name; - - Color color; - - FeatureTrack parent; - - String txtColor; - - String note; - - public abstract Object clone(); - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#toString() - */ - public String toString() - { - String str = "Segment: " + name + " " + start + " " + end; - if ((note != null) && (!note.equals("null"))) - if (note.length() > 40) - str += note.substring(0, 39) + "..."; - else - str += note; - return str; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#getNote() - */ - public String getNote() - { - return note; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#setNote(java.lang.String) - */ - public void setNote(String note) - { - this.note = note; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#setStart(int) - */ - public void setStart(int strt) - { - start = strt; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#getStart() - */ - public int getStart() - { - return start; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#setEnd(int) - */ - public void setEnd(int ed) - { - end = ed; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#getEnd() - */ - public int getEnd() - { - return end; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#setName(java.lang.String) - */ - public void setName(String nam) - { - name = nam; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#getName() - */ - public String getName() - { - return name; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#setColor(java.awt.Color) - */ - public void setColor(Color col) - { - color = col; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#getColor() - */ - public Color getColor() - { - return color; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#setParent(org.biojava.spice.feature.Feature) - */ - public void setParent(FeatureTrack f) - { - parent = f; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#getParent() - */ - public FeatureTrack getParent() - { - return parent; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#setTxtColor(java.lang.String) - */ - public void setTxtColor(String str) - { - txtColor = str; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#getTxtColor() - */ - public String getTxtColor() - { - return txtColor; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#overlaps(int) - */ - public boolean overlaps(int seqPosition) - { - if ((getStart() <= seqPosition) && (getEnd() >= seqPosition)) - { - return true; - } - return false; - } - - /* - * (non-Javadoc) - * - * @see org.biojava.spice.feature.SegmentIF#overlaps(org.biojava.spice.feature.Segment) - */ - public boolean overlaps(Segment segment) - { - if (!(this.start <= this.end)) - throw new IndexOutOfBoundsException("start > end for segment" + this); - - if (!(segment.getStart() <= segment.getEnd())) - throw new IndexOutOfBoundsException("start > end for segment" - + segment); - - // start must be in region of other - if (this.start >= segment.getStart()) - { - if (this.start <= segment.getEnd()) - { - return true; - } - } - // or end must be in region of other.. - if (this.end >= segment.getStart()) - { - if (this.end <= segment.getEnd()) - { - return true; - } - } - - if (this.start <= segment.getStart()) - { - if (this.end >= segment.getEnd()) - { - return true; - } - } - return false; - } -} diff --git a/src/org/biojava/dasobert/feature/FeatureComparator.java b/src/org/biojava/dasobert/feature/FeatureComparator.java deleted file mode 100644 index 2b75c22..0000000 --- a/src/org/biojava/dasobert/feature/FeatureComparator.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 23.09.2004 - * @author Andreas Prlic - * - */ - -package org.biojava.dasobert.feature; - -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; - -/** - * a comparator to sort Features byt type - * - * @author Andreas Prlic - */ - -public class FeatureComparator implements Comparator -{ - - public FeatureComparator() - { - } - - public int compare(Object a, Object b) - { - FeatureTrack x = (FeatureTrack) a; - FeatureTrack y = (FeatureTrack) b; - - String typea = x.getType(); - String typeb = y.getType(); - - if (!typea.equals(typeb)) - return typea.compareTo(typeb); - - List s1 = x.getSegments(); - List s2 = y.getSegments(); - - Iterator iter1 = s1.iterator(); - Iterator iter2 = s2.iterator(); - - while (iter1.hasNext()) - { - Segment seg1 = (Segment) iter1.next(); - int start1 = seg1.getStart(); - - while (iter2.hasNext()) - { - Segment seg2 = (Segment) iter2.next(); - int start2 = seg2.getStart(); - - if (start1 < start2) - { - return -1; - } - if (start1 > start2) - { - return 1; - } - - } - } - - return 0; - - } - -} diff --git a/src/org/biojava/dasobert/feature/FeatureMapComparator.java b/src/org/biojava/dasobert/feature/FeatureMapComparator.java deleted file mode 100644 index aa38981..0000000 --- a/src/org/biojava/dasobert/feature/FeatureMapComparator.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 23.09.2004 - * @author Andreas Prlic - * - */ - -package org.biojava.dasobert.feature; - -import java.util.Comparator; -import java.util.Map; - -/** - * a comparator to sort Features if they are still in a Map ( sorts by type ) - * - * @author Andreas Prlic - */ - -public class FeatureMapComparator implements Comparator -{ - - public FeatureMapComparator() - { - } - - public int compare(Object a, Object b) - { - Map x = (Map) a; - Map y = (Map) b; - - String typea = (String) x.get("TYPE"); - String typeb = (String) y.get("TYPE"); - - if (isSecstruc(typea) && isSecstruc(typeb)) - { - return 0; - } - return typea.compareTo(typeb); - } - - public boolean isSecstruc(String type) - { - if (type.equals("HELIX") || type.equals("STRAND") - || type.equals("TURN")) - { - return true; - } - return false; - } - -} diff --git a/src/org/biojava/dasobert/feature/FeatureTrack.java b/src/org/biojava/dasobert/feature/FeatureTrack.java deleted file mode 100644 index e7b6bbd..0000000 --- a/src/org/biojava/dasobert/feature/FeatureTrack.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Feb 9, 2005 - * - */ -package org.biojava.dasobert.feature; - -import java.util.List; - -/** - * A feature corresponds to a track in Ensembl - * - * @author Andreas Prlic - * - */ -public interface FeatureTrack -{ - - public Object clone(); - - /** - * returns true if the specified sequence position is within the range of this - * Feature - * - * @param seqPosition - * the position to check - * @return true if the position is within the ranges of the segments of this - * feature - */ - public boolean overlaps(int seqPosition); - - public String toString(); - - public void setSource(String s); - - public String getSource(); - - public void setName(String nam); - - public String getName(); - - public void setMethod(String methd); - - public String getMethod(); - - public void setType(String typ); - - public String getType(); - - public void setNote(String nte); - - public String getNote(); - - public void setLink(String lnk); - - public String getLink(); - - public void setScore(String score); - - public String getScore(); - - public void setOrientation(String orientation); - - public String getOrientation(); - - /** - * test if two features are equivalent - * - * @param feat - * feature to compare with - * @return true if equivalend - */ - public abstract boolean equals(FeatureTrack feat); - - /** - * add a segment to this feature - * - * @param start - * position - * @param end - * position - * @param name - * of feature - */ - public abstract void addSegment(int start, int end, String name); - - public abstract void addSegment(Segment s); - - public abstract List getSegments(); - - /** - * set the data from the DAS - type - id field (used for Ontology support) - * - * @param typeID - */ - public void setTypeID(String typeID); - - /** - * set the data from the DAS - type - category field (used for Ontology - * support) - * - * @param typeCategory - */ - public void setTypeCategory(String typeCategory); - - public String getTypeID(); - - public String getTypeCategory(); - -} \ No newline at end of file diff --git a/src/org/biojava/dasobert/feature/FeatureTrackConverter.java b/src/org/biojava/dasobert/feature/FeatureTrackConverter.java deleted file mode 100644 index 4818e10..0000000 --- a/src/org/biojava/dasobert/feature/FeatureTrackConverter.java +++ /dev/null @@ -1,526 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on Dec 5, 2007 - * - */ - -package org.biojava.dasobert.feature; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** - * converts the features from their "raw" representation as a Map into a Feature - * class - * - * @author Andreas Prlic - * - */ -public class FeatureTrackConverter -{ - - public static final Color HELIX_COLOR = new Color(255, 51, 51); - - public static final Color STRAND_COLOR = new Color(255, 204, 51); - - public static final Color TURN_COLOR = new Color(204, 204, 204); - - // some annotation types, for which there is a special treatment - public static final String DISULFID_TYPE = "DISULFID"; - - public static final String SECSTRUC_TYPE = "SECSTRUC"; - - public static final String METAL_TYPE = "METAL"; - - public static final String MSD_SITE_TYPE = "MSD_SITE"; - - String type; - - public static final String TYPE_HISTOGRAM = "histogram"; - - public static final String TYPE_DEFAULT = "default"; - - // rotate between these colors - public static final Color[] entColors = new Color[] - { new Color(51, 51, 255), // blue - new Color(102, 255, 255), // cyan - new Color(153, 255, 153), // green - new Color(153, 255, 153), // green - new Color(255, 153, 153), // pink - new Color(255, 51, 51), // red - new Color(255, 51, 255) // pink - }; - - public static final String[] txtColors = new String[] - { "blue", "pink", "green", "yellow", "red", "cyan", "pink" }; - - Map[] stylesheet; - - boolean isHistogram = false; - - public FeatureTrackConverter() - { - type = TYPE_DEFAULT; - stylesheet = new Map[0]; - } - - public FeatureTrackConverter(Map[] stylesheet) - { - - if (stylesheet == null) - stylesheet = new Map[0]; - - this.stylesheet = stylesheet; - - } - - public FeatureTrackConverter(Map[] stylesheet, boolean isHistogram) - { - this(stylesheet); - this.isHistogram = isHistogram; - if (isHistogram) - type = TYPE_HISTOGRAM; - } - - public String getType() - { - return type; - } - - public void setType(String type) - { - if (type.equals(TYPE_HISTOGRAM)) - isHistogram = true; - this.type = type; - } - - public boolean isHistogram() - { - return isHistogram; - } - - public void setHistogram(boolean isHistogram) - { - this.isHistogram = isHistogram; - } - - public FeatureTrack[] convertMap2Features(Map[] mapfeatures) - { - List features = new ArrayList(); - - boolean first = true; - boolean secstruc = false; - boolean isGroup = false; - - FeatureTrack feat = null; - Segment segment = null; - - int featuresCounter = 0; - String prevGroup = null; - - for (int i = 0; i < mapfeatures.length; i++) - { - - Map currentFeatureMap = mapfeatures[i]; - String type = (String) currentFeatureMap.get("TYPE"); - - String group = (String) currentFeatureMap.get("GROUP"); - if (group != null) - { - if (prevGroup != null) - { - if (group.equals(prevGroup)) - { - feat.setName(group); - isGroup = true; - } - else - { - isGroup = false; - } - } - else - { - isGroup = false; - } - } - else - { - isGroup = false; - } - - // we are skipping literature references for the moment - // TODO: add a display to spice for non-positional features - // - if (type.equals("reference") || type.equals("GOA")) - { - continue; - } - - if (!first) - { - // if not first feature - - if ((!secstruc) && (!isGroup)) - { - - // if not secondary structure and not in a group ... - features = testAddFeatures(features, feat); - - } - else if (!(type.equals("HELIX") || type.equals("STRAND") || type - .equals("TURN"))) - { - // end of secondary structure - secstruc = false; - if (feat != null && (!isGroup)) - { - features = testAddFeatures(features, feat); - } - - } - } // end of not first - - first = false; - if ((!secstruc) && (!isGroup)) - { - featuresCounter += 1; - feat = getNewFeat(currentFeatureMap); - } - - if (type.equals("STRAND")) - { - secstruc = true; - currentFeatureMap.put("colorTxt", "yellow"); - feat.setName("SECSTRUC"); - feat.setType("SECSTRUC"); - } - - else if (type.equals("HELIX")) - { - secstruc = true; - currentFeatureMap.put("colorTxt", "red"); - feat.setName("SECSTRUC"); - feat.setType("SECSTRUC"); - } - - else if (type.equals("TURN")) - { - secstruc = true; - currentFeatureMap.put("colorTxt", "white"); - - feat.setName("SECSTRUC"); - feat.setType("SECSTRUC"); - } - else - { - secstruc = false; - currentFeatureMap.put("colorTxt", txtColors[featuresCounter - % txtColors.length]); - if (!isGroup) - { - try - { - feat.setName(type); - - } catch (NullPointerException e) - { - // e.printStackTrace(); - feat.setName("null"); - } - } - } - - segment = getNewSegment(currentFeatureMap); - - feat.addSegment(segment); - prevGroup = group; - } - - if (feat != null) - features = testAddFeatures(features, feat); - - return (FeatureTrack[]) features.toArray(new FeatureTrack[features - .size()]); - } - - /** - * test if this features is added as a new feature to the features list, or if - * it is joint with an already existing one... - * - * @param features - * @param newFeature - * @return a List of FeatureTrack objects - */ - protected List testAddFeatures(List features, FeatureTrack newFeature) - { - - // System.out.println("testing " + newFeature + " " + - // newFeature.getScore()); - Iterator iter = features.iterator(); - - if (isHistogramFeatureType(newFeature)) - { - - // return histogram type features - type = TYPE_HISTOGRAM; - - Segment seg = getHistogramSegmentFromFeature(newFeature); - - while (iter.hasNext()) - { - FeatureTrack knownFeature = (FeatureTrack) iter.next(); - String knownType = knownFeature.getType(); - - // System.out.println("found histogram style " + feat); - // set type of this DAS source to being HISTOGRAM style - - if (knownType.equals(newFeature.getType())) - { - // convert the feature into a HistogramSegment and add to the already - // known feature - - knownFeature.addSegment(seg); - // we can return now - return features; - } - - } - // we could not link this to any existing feature - // convert it to a new HistogramFeature - HistogramFeature hfeat = new HistogramFeature(); - - hfeat.setLink(newFeature.getLink()); - hfeat.setMethod(newFeature.getMethod()); - hfeat.setName(newFeature.getName()); - hfeat.setNote(newFeature.getNote()); - hfeat.setScore("0"); - hfeat.setSource(newFeature.getSource()); - hfeat.addSegment(seg); - hfeat.setType(newFeature.getType()); - - newFeature = hfeat; - features.add(newFeature); - return features; - } - - while (iter.hasNext()) - { - FeatureTrack knownFeature = (FeatureTrack) iter.next(); - // this only compares method source and type ... - boolean sameFeat = false; - if (knownFeature.equals(newFeature)) - sameFeat = true; - - if ((knownFeature.getSource().equals(newFeature.getSource())) - && (knownFeature.getMethod().equals(newFeature.getMethod())) - && (knownFeature.getNote().equals(newFeature.getNote())) - && isSecondaryStructureFeat(knownFeature) - && isSecondaryStructureFeat(newFeature)) - sameFeat = true; - - if (sameFeat) - { - - // seems to be of same type, method and source, so check if the segments - // can be joined - - List tmpsegs = knownFeature.getSegments(); - Iterator segiter = tmpsegs.iterator(); - List newsegs = newFeature.getSegments(); - Iterator newsegsiter = newsegs.iterator(); - boolean overlap = false; - while (newsegsiter.hasNext()) - { - Segment newseg = (Segment) newsegsiter.next(); - - while (segiter.hasNext()) - { - Segment tmpseg = (Segment) segiter.next(); - - if (tmpseg.overlaps(newseg)) - overlap = true; - } - } - - if (!overlap) - { - // add all new segments to old features... - newsegsiter = newsegs.iterator(); - while (newsegsiter.hasNext()) - { - Segment newseg = (Segment) newsegsiter.next(); - knownFeature.addSegment(newseg); - } - - return features; - } - } - - } - - // if we get here, the features could not be joint with any other one, so - // there is always some overlap - // add to the list of known features - features.add(newFeature); - return features; - } - - private FeatureTrack getNewFeat(Map currentFeatureMap) - { - FeatureTrack feat = new FeatureTrackImpl(); - // logger.finest(currentFeatureMap); - // System.out.println("DrawableDasSource " + currentFeatureMap); - feat.setSource((String) currentFeatureMap.get("dassource")); - feat.setName((String) currentFeatureMap.get("NAME")); - feat.setType((String) currentFeatureMap.get("TYPE")); - feat.setLink((String) currentFeatureMap.get("LINK")); - feat.setNote((String) currentFeatureMap.get("NOTE")); - - String typeID = (String) currentFeatureMap.get("TYPE_ID"); - String typeCategory = (String) currentFeatureMap.get("TYPE_CATEGORY"); - feat.setTypeID(typeID); - feat.setTypeCategory(typeCategory); - - String method = (String) currentFeatureMap.get("METHOD"); - if (method == null) - { - method = ""; - } - feat.setMethod(method); - feat.setScore((String) currentFeatureMap.get("SCORE")); - return feat; - } - - private Segment getNewSegment(Map featureMap) - { - Segment s = new SegmentImpl(); - String sstart = (String) featureMap.get("START"); - String send = (String) featureMap.get("END"); - int start = Integer.parseInt(sstart); - int end = Integer.parseInt(send); - s.setStart(start); - s.setEnd(end); - s.setName((String) featureMap.get("TYPE")); - s.setTxtColor((String) featureMap.get("colorTxt")); - s.setColor((Color) featureMap.get("color")); - s.setNote((String) featureMap.get("NOTE")); - return s; - - } - - private boolean isSecondaryStructureFeat(FeatureTrack feat) - { - String type = feat.getType(); - if (type.equals("HELIX") || type.equals("STRAND") - || type.equals("TURN")) - return true; - return false; - } - - private boolean isHistogramFeatureType(FeatureTrack feat) - { - String ftype = feat.getType(); - - Map[] style = stylesheet; - - // System.out.println("is HistogramFeature type " + ftype + " " + style ); - - // todo : move this info into a config file... - - if (ftype.equals("hydrophobicity")) - { - return true; - } - if (getType().equals(TYPE_HISTOGRAM)) - return true; - - if (style != null) - { - - for (int i = 0; i < style.length; i++) - { - Map m = style[i]; - - // make sure the stylesheet is for this feature type - String styleType = (String) m.get("type"); - if (styleType != null) - { - if (!styleType.equals(ftype)) - { - continue; - } - } - else - { - continue; - } - - String type = (String) m.get("style"); - if (type != null) - { - // System.out.println("stylesheet type " + type); - if (type.equals("gradient") || (type.equals("lineplot")) - || (type.equals("histogram"))) - { - - return true; - } - } - } - } - - return false; - } - - private HistogramSegment getHistogramSegmentFromFeature(FeatureTrack feat) - { - HistogramSegment s = new HistogramSegment(); - - double score = 0.0; - - try - { - score = Double.parseDouble(feat.getScore()); - - } catch (Exception e) - { - // e.printStackTrace(); - } - s.setScore(score); - List segments = feat.getSegments(); - if (segments.size() > 0) - { - Segment seg = (Segment) segments.get(0); - s.setName(seg.getName()); - s.setStart(seg.getStart()); - s.setEnd(seg.getEnd()); - s.setNote(seg.getNote()); - s.setColor(seg.getColor()); - s.setTxtColor(seg.getTxtColor()); - } - - return s; - } - -} diff --git a/src/org/biojava/dasobert/feature/FeatureTrackImpl.java b/src/org/biojava/dasobert/feature/FeatureTrackImpl.java deleted file mode 100644 index a13fbb3..0000000 --- a/src/org/biojava/dasobert/feature/FeatureTrackImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 22.09.2004 - * @author Andreas Prlic - * - */ - -package org.biojava.dasobert.feature; - -import java.util.Iterator; - -/** - * a class to store FeatureData and to visualize them coordinate system of - * features is always UniProt ! PDBresnum features served by DAS need to be - * converted into UniProt coord sys first. - * - * a feature consists of one or several segments. segmetns cotnains and - * information. - * - * @author Andreas Prlic - */ -public class FeatureTrackImpl extends AbstractFeatureTrack implements - FeatureTrack - -{ - - public Object clone() - { - - FeatureTrack f = new FeatureTrackImpl(); - f.setName(name); - f.setMethod(method); - f.setType(type); - f.setNote(note); - f.setLink(link); - f.setSource(source); - f.setScore(score); - - Iterator iter = segments.iterator(); - - while (iter.hasNext()) - { - Segment s = (Segment) iter.next(); - f.addSegment((Segment) s.clone()); - } - - return f; - - } - -} diff --git a/src/org/biojava/dasobert/feature/HistogramFeature.java b/src/org/biojava/dasobert/feature/HistogramFeature.java deleted file mode 100644 index 8663081..0000000 --- a/src/org/biojava/dasobert/feature/HistogramFeature.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on May 22, 2007 - * - */ - -package org.biojava.dasobert.feature; - -import java.util.Iterator; - -/** - * a class that represents Histogram Style features in addition to normal - * features they know about Max and Minimum scores for the whole line Histogram - * feautes have only one (Histogram) Segment, which contains the scores for each - * position - * - * @author Andreas Prlic - * - */ -public class HistogramFeature extends AbstractFeatureTrack -{ - - double max; - - double min; - - public HistogramFeature() - { - super(); - // TODO Auto-generated constructor stub - } - - public double getMax() - { - return max; - } - - public void setMax(double max) - { - this.max = max; - } - - public double getMin() - { - return min; - } - - public void setMin(double min) - { - this.min = min; - } - - public Object clone() - { - - HistogramFeature f = new HistogramFeature(); - - f.setName(name); - f.setMethod(method); - f.setType(type); - f.setNote(note); - f.setLink(link); - f.setSource(source); - f.setScore(score); - - Iterator iter = segments.iterator(); - - while (iter.hasNext()) - { - Segment s = (Segment) iter.next(); - f.addSegment((Segment) s.clone()); - } - - return f; - - } - -} diff --git a/src/org/biojava/dasobert/feature/HistogramSegment.java b/src/org/biojava/dasobert/feature/HistogramSegment.java deleted file mode 100644 index 7a7ea25..0000000 --- a/src/org/biojava/dasobert/feature/HistogramSegment.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on May 22, 2007 - * - */ - -package org.biojava.dasobert.feature; - -/** - * a Histogram segment is an extension of the standard Segment with a score - * - * @author Andreas Prlic - * - */ -public class HistogramSegment extends AbstractSegment -{ - - double score; - - public HistogramSegment() - { - super(); - - } - - public double getScore() - { - return score; - } - - public void setScore(double score) - { - this.score = score; - } - - public Object clone() - { - - Segment s = new HistogramSegment(); - s.setStart(start); - s.setEnd(end); - s.setName(name); - s.setColor(color); - s.setTxtColor(txtColor); - s.setNote(note); - return s; - - } - -} diff --git a/src/org/biojava/dasobert/feature/Segment.java b/src/org/biojava/dasobert/feature/Segment.java deleted file mode 100644 index 78e2840..0000000 --- a/src/org/biojava/dasobert/feature/Segment.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on 22.09.2004 - * @author Andreas Prlic - * - */ - -package org.biojava.dasobert.feature; - -import java.awt.Color; - -/** a class to keep track of location information for a feature */ -public interface Segment -{ - - public Object clone(); - - public String toString(); - - public String getNote(); - - public void setNote(String note); - - public void setStart(int strt); - - public int getStart(); - - public void setEnd(int ed); - - public int getEnd(); - - public void setName(String nam); - - public String getName(); - - public void setColor(Color col); - - public Color getColor(); - - public void setParent(FeatureTrack f); - - public FeatureTrack getParent(); - - public void setTxtColor(String str); - - public String getTxtColor(); - - /** - * returns true if the specified sequence position is within the range of this - * Segment - * - * @param seqPosition - * the position to check - * @return true if seqPos >= start && seqPos <= end - */ - public boolean overlaps(int seqPosition); - - /** - * tests if two segments are overlapping - * - * @param segment - * to compare with - * @return true if segments overlap - */ - public boolean overlaps(Segment segment); - -} diff --git a/src/org/biojava/dasobert/feature/SegmentComparator.java b/src/org/biojava/dasobert/feature/SegmentComparator.java deleted file mode 100644 index 68a2c16..0000000 --- a/src/org/biojava/dasobert/feature/SegmentComparator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on May 22, 2007 - * - */ - -package org.biojava.dasobert.feature; - -import java.util.Comparator; - -public class SegmentComparator implements Comparator -{ - - public int compare(Object arg0, Object arg1) - { - - Segment s1 = (Segment) arg0; - Segment s2 = (Segment) arg1; - - if (s1.getStart() < s2.getStart()) - return -1; - if (s1.getStart() > s2.getStart()) - return 1; - - return 0; - } - -} diff --git a/src/org/biojava/dasobert/feature/SegmentImpl.java b/src/org/biojava/dasobert/feature/SegmentImpl.java deleted file mode 100644 index dba25e9..0000000 --- a/src/org/biojava/dasobert/feature/SegmentImpl.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * BioJava development code - * - * This code may be freely distributed and modified under the - * terms of the GNU Lesser General Public Licence. This should - * be distributed with the code. If you do not have a copy, - * see: - * - * http://www.gnu.org/copyleft/lesser.html - * - * Copyright for this code is held jointly by the individual - * authors. These should be listed in @author doc comments. - * - * For more information on the BioJava project and its aims, - * or to join the biojava-l mailing list, visit the home page - * at: - * - * http://www.biojava.org/ - * - * Created on May 22, 2007 - * - */ - -package org.biojava.dasobert.feature; - -import java.awt.Color; - -public class SegmentImpl extends AbstractSegment -{ - - public SegmentImpl() - { - super(); - start = 0; - end = 0; - name = "Unknown"; - color = Color.white; - txtColor = "white"; - parent = null; - note = ""; - } - - public boolean equals(Segment s) - { - if (s == null) - return false; - - if ((start == s.getStart()) && (end == s.getEnd()) - && (name.equals(s.getName()))) - { - if (note == null) - { - if (s.getNote() == null) - return true; - } - else - { - if (s.getNote() != null) - { - if (s.getNote().equals(note)) - return true; - } - } - - } - - return false; - } - - public Object clone() - { - - Segment s = new SegmentImpl(); - s.setStart(start); - s.setEnd(end); - s.setName(name); - s.setColor(color); - s.setTxtColor(txtColor); - s.setNote(note); - return s; - - } -} -- 1.7.10.2