001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021 022package org.biojava.bio.program.tagvalue; 023 024import java.util.List; 025import java.util.Map; 026 027import org.biojava.utils.ParserException; 028import org.biojava.utils.SmallMap; 029 030/** 031 * <p> 032 * A mapping between keys and actions to turn old values into new values. 033 * </p> 034 * 035 * @author Matthew Pocock 036 * @since 1.3 037 */ 038public class ChangeTable { 039 public static final Changer STRING_TO_INT = new Changer() { 040 public Object change(Object val) { 041 return new Integer((String) val); 042 } 043 }; 044 045 private final Map changers; 046 private final Map splitters; 047 048 public ChangeTable() { 049 this.changers = new SmallMap(); 050 this.splitters = new SmallMap(); 051 } 052 053 054 /** 055 * Set the Changer to be used for all values of a particular tag. 056 * 057 * @param tag the tag Object which will have all values changed 058 * @param changer the Changer used to change the values 059 */ 060 public void setChanger(Object tag, Changer changer) { 061 changers.put(tag, changer); 062 } 063 064 /** 065 * Set the Splitter to be used for all values of a particular tag. 066 * 067 * @param tag the tag Object which will have all values split 068 * @param splitter the Splitter used to split the values 069 */ 070 public void setSplitter(Object tag, Splitter splitter) { 071 splitters.put(tag, splitter); 072 } 073 074 /** 075 * Get the Changer currently registered to handle a tag. 076 * 077 * @param tag the tag Object for which values would be changed 078 * @return the associated Changer or null 079 */ 080 public Changer getChanger(Object tag) { 081 return (Changer) changers.get(tag); 082 } 083 084 /** 085 * Get the Splitter currently registered to handle a tag. 086 * 087 * @param tag the tag Object for which values would be split 088 * @return the associated Splitter or null 089 */ 090 public Splitter getSplitter(Object tag) { 091 return (Splitter) splitters.get(tag); 092 } 093 094 public Object change(Object tag, Object value) 095 throws ParserException { 096 Changer c = (Changer) changers.get(tag); 097 if(c != null) { 098 return c.change(value); 099 } 100 101 Splitter s = (Splitter) splitters.get(tag); 102 if(s != null) { 103 return s.split(value); 104 } 105 106 return value; 107 } 108 109 /** 110 * Callback used to produce a new value from an old one. 111 * 112 * @author Matthew Pocock 113 * @since 1.3 114 */ 115 public static interface Changer { 116 /** 117 * <p> 118 * Produce a modified value from an old value. 119 * </p> 120 * 121 * <p> 122 * It is strongly recommended that this method is re-entrant and does not 123 * modify the state of the Changer in a way that would affect future return 124 * -values. 125 * </p> 126 * 127 * @param value the old value Object 128 * @return the new value Object 129 * @throws ParserException if value could not be changed 130 */ 131 public Object change(Object value) 132 throws ParserException; 133 } 134 135 /** 136 * Callback used to produce a list of values from a single old one. 137 * 138 * @author Matthew Pocock 139 * @since 1.3 140 */ 141 public static interface Splitter { 142 /** 143 * <p> 144 * Produce a list of values from an old value. 145 * </p> 146 * 147 * <p> 148 * It is strongly recommended that this method is re-entrant and does not 149 * modify the state of the Splitter in a way that would affect future return 150 * -values. 151 * </p> 152 * 153 * @param value the old value Object 154 * @return a List of value Objects produced by splitting the old value 155 * Object 156 * @throws ParserException if the value could not be split 157 */ 158 public List split(Object value) 159 throws ParserException; 160 } 161 162 /** 163 * An implementation of Changer that applies a list of Changer instances to 164 * the value in turn. 165 * 166 * @author Matthew Pocock 167 * @since 1.3 168 */ 169 public static class ChainedChanger 170 implements Changer { 171 private Changer[] changers; 172 173 public ChainedChanger(Changer[] changers) { 174 this.changers = new Changer[changers.length]; 175 176 System.arraycopy(changers, 0, this.changers, 0, changers.length); 177 } 178 179 public Object change(Object value) 180 throws ParserException { 181 for(int i = 0; i < changers.length; i++) { 182 value = changers[i].change(value); 183 } 184 185 return value; 186 } 187 } 188}