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; 023 024import java.util.AbstractMap; 025import java.util.AbstractSet; 026import java.util.Iterator; 027import java.util.Map; 028import java.util.Set; 029 030import org.biojava.bio.program.tagvalue.ChangeTable; 031import org.biojava.utils.ParserException; 032 033/** 034 * <code>AnnotationChanger</code> remaps the values of an 035 * <code>Annotation</code> to new values specified by a 036 * <code>ValueChanger</code>. This will modify the values 037 * associated with properties, but not the property names. 038 * 039 * For writing light-weigth adaptors to project one type of 040 * Annotation to another using a ChangeTable. 041 * 042 * @since 1.3 043 * @author Matthew Pocock 044 * 045 */ 046public class AnnotationChanger extends AbstractAnnotation 047{ 048 private final Annotation wrapped; 049 private final ChangeTable changer; 050 private final Map properties; 051 052 /** 053 * Creates a new <code>AnnotationChanger</code> using the 054 * specified <code>ValueChanger</code> to remap its values. 055 * 056 * @param wrapped an <code>Annotation</code>. 057 * @param changer a <code>ValueChanger</code>. 058 */ 059 public AnnotationChanger(Annotation wrapped, ChangeTable changer) { 060 this.wrapped = wrapped; 061 this.changer = changer; 062 this.properties = new MappedHash(); 063 } 064 065 /** 066 * <code>getWrapped</code> returns the <code>Annotation</code> 067 * being remapped. 068 * 069 * @return an <code>Annotation</code>. 070 */ 071 public Annotation getWrapped() { 072 return wrapped; 073 } 074 075 /** 076 * <code>getMapper</code> returns the <code>ValueChanger</code> being 077 * used to remap the <code>Annotation</code>. 078 * 079 * @return a <code>ValueChanger</code>. 080 */ 081 public ChangeTable getChanger() { 082 return changer; 083 } 084 085 /** 086 * <code>getProperties</code> returns the mapped contents of the 087 * underlying <code>Annotation</code> as a <code>Map</code>. 088 * 089 * @return a <code>Map</code>. 090 */ 091 public Map getProperties() { 092 return properties; 093 } 094 095 /** 096 * <code>propertiesAllocated</code> is a convenience method to see 097 * if we have allocated the properties <code>Map</code>. 098 * 099 * @return a <code>boolean</code> true if the properties have been 100 * allocated, false otherwise. 101 */ 102 public boolean propertiesAllocated() { 103 return true; 104 } 105 106 private class MappedHash extends AbstractMap { 107 public int size() { 108 return wrapped.asMap().size(); 109 } 110 111 public Set entrySet() { 112 return new WrappedSet(wrapped.asMap().entrySet()); 113 } 114 } 115 116 private class WrappedSet extends AbstractSet { 117 private Set entrySet; 118 119 public WrappedSet(Set entrySet) { 120 this.entrySet = entrySet; 121 } 122 123 public int size() { 124 return entrySet.size(); 125 } 126 127 public Iterator iterator() { 128 return new Iterator() { 129 Iterator i = entrySet.iterator(); 130 131 public boolean hasNext() { 132 return i.hasNext(); 133 } 134 135 public Object next() { 136 final Map.Entry entry = (Map.Entry) i.next(); 137 138 return new Map.Entry() { 139 public Object getKey() { 140 return entry.getKey(); 141 } 142 143 public Object getValue() { 144 try { 145 return changer.change(getKey(), entry.getValue()); 146 } catch (ParserException pe) { 147 throw new BioError(pe); 148 } 149 } 150 151 public Object setValue(Object value) { 152 return entry.setValue(value); 153 } 154 }; 155 } 156 157 public void remove() { 158 i.remove(); 159 } 160 }; 161 } 162 } 163}