001 /* 002 * Copyright 2007, 2012 Stephen Fisher and Junhyong Kim, University of 003 * Pennsylvania. 004 * 005 * This file is part of Glo-DB. 006 * 007 * Glo-DB is free software: you can redistribute it and/or modify it 008 * under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * Glo-DB is distributed in the hope that it will be useful, but 013 * WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with Glo-DB. If not, see <http://www.gnu.org/licenses/>. 019 * 020 * @(#)AbstractFeature.java 021 */ 022 023 package edu.upenn.gloDB; 024 025 import java.util.HashMap; 026 import java.util.Iterator; 027 028 /** 029 * AbstractFeature. 030 * 031 * @author Stephen Fisher 032 * @version $Id: AbstractFeature.java,v 1.1.2.10 2007/03/01 21:17:32 fisher Exp $ 033 */ 034 035 public abstract class AbstractFeature implements Feature { 036 037 /** The contig that underlies the positions. */ 038 protected String source; 039 040 /** 041 * This is similar to "qualifiers" in GenBank. ex: scores, strand 042 * (+/-), phase (within codon). Each key/value pair is delimited 043 * by a ";". the keys and values are separated by "=". ex: 044 * "scores=.; strand=+". Key based attribute searches are case 045 * sensitive. 046 * @XXX Should any of these be hardcoded as fields? 047 */ 048 // protected HashMap attributes = new HashMap(); 049 protected String attributes = ""; 050 051 052 /** 053 * Set the source when the Feature is created. Don't allow the 054 * source to change there after. 055 * @XXX Should throw an exception if source is null. 056 */ 057 public AbstractFeature(Sequence source) { 058 if (source == null) { 059 GloDBUtils.printMsg("No sequence info for feature.", 2); // error 060 } 061 this.source = source.getID(); 062 } 063 064 065 //-------------------------------------------------------------------------- 066 // Setters and Getters 067 068 /** Returns Feature type (see GloDBUtils) */ 069 public int getType() { return GloDBUtils.FEATURE; } 070 071 /** 072 * Set the attributes. 073 * @param attributes a String of Feature attributes 074 */ 075 public void setAttributes(String attributes) { 076 // make sure attributes is never set to null 077 if (GloDBUtils.isEmpty(attributes)) attributes = ""; 078 this.attributes = attributes; 079 } 080 081 /** 082 * Set the attributes using a HashMap. 083 * @param attribMap a HashMap of Feature attributes 084 */ 085 public void setAttributes(HashMap attribMap) { 086 // test for null or empty maps 087 if ((attribMap == null) || (attribMap.isEmpty())) { 088 this.attributes = ""; 089 return; 090 } 091 092 Iterator keys = attribMap.keySet().iterator(); 093 String key = (String) keys.next(); 094 String value = (String) attribMap.get(key); 095 String attribs = key + "=" + value; 096 097 while (keys.hasNext()) { 098 key = (String) keys.next(); 099 value = (String) attribMap.get(key); 100 attribs += ";" + key + "=" + value; 101 } 102 103 this.attributes = attribs; 104 } 105 106 /** Get the attributes. */ 107 public String getAttributes() { return attributes; } 108 // public HashMap getAttributes() { return attributes; } 109 110 /** 111 * Returns the underlying Sequence object. 112 * @return Returns the sequence object. 113 */ 114 public Sequence getSource() { return ObjectHandles.getSequence(source); } 115 116 /** Returns the underlying Sequence object's ID. */ 117 public String getSourceID() { return source; } 118 119 //-------------------------------------------------------------------------- 120 // Miscellaneous Methods 121 122 /** Add an attribute. */ 123 public void addAttribute(String key, String value) { 124 if (GloDBUtils.isEmpty(attributes)) attributes += key + "=" + value; 125 else attributes += ";" + key + "=" + value; 126 } 127 128 /** Add an attribute (key/value pair). */ 129 public void addAttribute(String value) { 130 if (GloDBUtils.isEmpty(attributes)) attributes += value; 131 else attributes += ";" + value; 132 } 133 134 /** Remove an attribute. This is case sensitive. */ 135 public void delAttribute(String key) { 136 if (GloDBUtils.isEmpty(attributes)) return; 137 138 String[] pairs = attributes.split(";"); 139 String newAttribs = ""; 140 141 for (int i = 0; i < pairs.length; i++) { 142 if (! pairs[i].startsWith(key)) { 143 if (i == 0) newAttribs += pairs[i]; 144 else newAttribs += ";" + pairs[i]; 145 } 146 } 147 148 this.attributes = newAttribs; 149 } 150 151 /** Returns true if attribute 'key' exists. This is case sensitive. */ 152 public boolean containsAttribute(String key) { 153 return attributes.matches(".*key\\s?=.+"); 154 } 155 156 /** 157 * Get the attributes as HashMap. If no attributes, then an empty 158 * HashMap is returned. 159 */ 160 public HashMap getAttributesMap() { 161 if (GloDBUtils.isEmpty(attributes)) return new HashMap(); 162 163 String[] pairs = attributes.split(";"); 164 165 HashMap attribMap = new HashMap(); 166 for (int i = 0; i < pairs.length; i++) { 167 String[] keyVal = pairs[i].split("="); 168 if (keyVal.length == 1) { 169 // this should never happen 170 attribMap.put(keyVal[0], keyVal[0]); 171 GloDBUtils.printWarning("Found potentially invalid Feature attributes (" + keyVal[0] + ") in " + attributes); 172 } else { 173 attribMap.put(keyVal[0], keyVal[1]); 174 } 175 } 176 177 return attribMap; 178 } 179 180 /** Get value for attribute 'key'. This is case sensitive. */ 181 public String getAttribute(String key) { 182 if (GloDBUtils.isEmpty(attributes)) return ""; 183 184 String[] pairs = attributes.split(";"); 185 186 for (int i = 0; i < pairs.length; i++) { 187 if (pairs[i].startsWith(key)) { 188 return pairs[i].split("=")[1]; 189 } 190 } 191 192 return ""; 193 } 194 195 /** Returns description and Feature information. */ 196 public String toString() { 197 String out = ""; 198 199 // will convert itself to a string 200 if (attributes == null) { 201 out += "Attributes: none"; 202 } else { 203 out += "Attributes:\n " + attributes; 204 } 205 out += "\nSource: " + source + "\n"; 206 207 return out; 208 } 209 210 } // AbstractxFeature.java