11 |
13 Sep 07 |
nicklas |
1 |
///////////////////////////////////////////////////////////////// |
11 |
13 Sep 07 |
nicklas |
2 |
// |
11 |
13 Sep 07 |
nicklas |
// Copyright (C) 2005 Affymetrix, Inc. |
11 |
13 Sep 07 |
nicklas |
4 |
// |
11 |
13 Sep 07 |
nicklas |
// This library is free software; you can redistribute it and/or modify |
11 |
13 Sep 07 |
nicklas |
// it under the terms of the GNU Lesser General Public License as published |
11 |
13 Sep 07 |
nicklas |
// by the Free Software Foundation; either version 2.1 of the License, |
11 |
13 Sep 07 |
nicklas |
// or (at your option) any later version. |
11 |
13 Sep 07 |
nicklas |
9 |
// |
11 |
13 Sep 07 |
nicklas |
// This library is distributed in the hope that it will be useful, but |
11 |
13 Sep 07 |
nicklas |
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
11 |
13 Sep 07 |
nicklas |
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License |
11 |
13 Sep 07 |
nicklas |
// for more details. |
11 |
13 Sep 07 |
nicklas |
14 |
// |
11 |
13 Sep 07 |
nicklas |
// You should have received a copy of the GNU Lesser General Public License |
11 |
13 Sep 07 |
nicklas |
// along with this library; if not, write to the Free Software Foundation, Inc., |
11 |
13 Sep 07 |
nicklas |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
11 |
13 Sep 07 |
nicklas |
18 |
// |
11 |
13 Sep 07 |
nicklas |
19 |
///////////////////////////////////////////////////////////////// |
11 |
13 Sep 07 |
nicklas |
20 |
|
11 |
13 Sep 07 |
nicklas |
21 |
|
11 |
13 Sep 07 |
nicklas |
22 |
package affymetrix.calvin.data; |
11 |
13 Sep 07 |
nicklas |
23 |
|
11 |
13 Sep 07 |
nicklas |
24 |
import java.util.*; |
11 |
13 Sep 07 |
nicklas |
25 |
import affymetrix.calvin.parameter.*; |
11 |
13 Sep 07 |
nicklas |
26 |
|
11 |
13 Sep 07 |
nicklas |
/** Holds data associated with tiling array CHP files. */ |
11 |
13 Sep 07 |
nicklas |
28 |
public class CHPTilingData { |
11 |
13 Sep 07 |
nicklas |
29 |
|
11 |
13 Sep 07 |
nicklas |
/** The identifier to identify a tiling CHP file. */ |
11 |
13 Sep 07 |
nicklas |
31 |
public static final String CHP_TILING_TYPE = "affymetrix-tiling-analysis"; |
11 |
13 Sep 07 |
nicklas |
32 |
|
11 |
13 Sep 07 |
nicklas |
/** The identifier for the type of data stored in the file. */ |
11 |
13 Sep 07 |
nicklas |
34 |
public static final String TILING_DATA_TYPE= "file_type"; |
11 |
13 Sep 07 |
nicklas |
35 |
|
11 |
13 Sep 07 |
nicklas |
/** The identifier for the scale of the data. */ |
11 |
13 Sep 07 |
nicklas |
37 |
public static final String TILING_PARAM_SUFFIX= "Param-"; |
11 |
13 Sep 07 |
nicklas |
38 |
|
11 |
13 Sep 07 |
nicklas |
/** The identifier for the algorithms tail type. */ |
11 |
13 Sep 07 |
nicklas |
40 |
public static final String TILING_NUM_SEQS= "NumberSequences"; |
11 |
13 Sep 07 |
nicklas |
41 |
|
11 |
13 Sep 07 |
nicklas |
/** The identifier for the algorithm name. */ |
11 |
13 Sep 07 |
nicklas |
43 |
public static final String TILING_ALG_NAME= "Algorithm-Name"; |
11 |
13 Sep 07 |
nicklas |
44 |
|
11 |
13 Sep 07 |
nicklas |
/** The identifier for the algorithm version. */ |
11 |
13 Sep 07 |
nicklas |
46 |
public static final String TILING_ALG_VERSION= "Algorithm-Version"; |
11 |
13 Sep 07 |
nicklas |
47 |
|
11 |
13 Sep 07 |
nicklas |
/** The name of the tiling data group. */ |
11 |
13 Sep 07 |
nicklas |
49 |
public static final String CHP_TILING_GROUP= "Tiling Results"; |
11 |
13 Sep 07 |
nicklas |
50 |
|
11 |
13 Sep 07 |
nicklas |
/** The id for the sequence name. */ |
11 |
13 Sep 07 |
nicklas |
52 |
public static final String TILING_SEQ_NAME= "Name"; |
11 |
13 Sep 07 |
nicklas |
53 |
|
11 |
13 Sep 07 |
nicklas |
/** The id for the sequence group name. */ |
11 |
13 Sep 07 |
nicklas |
55 |
public static final String TILING_SEQ_GROUP_NAME= "GroupName"; |
11 |
13 Sep 07 |
nicklas |
56 |
|
11 |
13 Sep 07 |
nicklas |
/** The id for the sequence version. */ |
11 |
13 Sep 07 |
nicklas |
58 |
public static final String TILING_SEQ_VERSION= "Version"; |
11 |
13 Sep 07 |
nicklas |
59 |
|
11 |
13 Sep 07 |
nicklas |
/** The value to indicate signal values are stored in the CHP file. */ |
11 |
13 Sep 07 |
nicklas |
61 |
public static final String TILING_SIGNAL_VALUES= "Signal"; |
11 |
13 Sep 07 |
nicklas |
62 |
|
11 |
13 Sep 07 |
nicklas |
/** The value to indicate p-values are stored in the CHP file. */ |
11 |
13 Sep 07 |
nicklas |
64 |
public static final String TILING_PVALUE_VALUES= "p-value"; |
11 |
13 Sep 07 |
nicklas |
65 |
|
11 |
13 Sep 07 |
nicklas |
/** column name for position */ |
11 |
13 Sep 07 |
nicklas |
67 |
private static final String GenomicPositionColName = "Genomic Position"; |
11 |
13 Sep 07 |
nicklas |
68 |
|
11 |
13 Sep 07 |
nicklas |
/** column name for p-value */ |
11 |
13 Sep 07 |
nicklas |
70 |
private static final String PValueColName = "p-value"; |
11 |
13 Sep 07 |
nicklas |
71 |
|
11 |
13 Sep 07 |
nicklas |
/** Constructor */ |
11 |
13 Sep 07 |
nicklas |
73 |
public CHPTilingData() { |
11 |
13 Sep 07 |
nicklas |
74 |
entries = null; |
11 |
13 Sep 07 |
nicklas |
75 |
clear(); |
11 |
13 Sep 07 |
nicklas |
76 |
genericData = new GenericData(); |
11 |
13 Sep 07 |
nicklas |
77 |
} |
11 |
13 Sep 07 |
nicklas |
78 |
|
11 |
13 Sep 07 |
nicklas |
/** Constructor with file name. |
11 |
13 Sep 07 |
nicklas |
* @param filename The name of the CHP file. |
11 |
13 Sep 07 |
nicklas |
81 |
*/ |
11 |
13 Sep 07 |
nicklas |
82 |
public CHPTilingData(String filename) { |
11 |
13 Sep 07 |
nicklas |
83 |
entries = null; |
11 |
13 Sep 07 |
nicklas |
84 |
clear(); |
11 |
13 Sep 07 |
nicklas |
85 |
genericData = new GenericData(); |
11 |
13 Sep 07 |
nicklas |
86 |
setFilename(filename); |
11 |
13 Sep 07 |
nicklas |
87 |
DataGroupHeader dcHdr = new DataGroupHeader(CHP_TILING_GROUP); |
11 |
13 Sep 07 |
nicklas |
88 |
genericData.getHeader().addDataGroupHdr(dcHdr); |
11 |
13 Sep 07 |
nicklas |
89 |
genericData.getHeader().getGenericDataHdr().setFileTypeId(CHP_TILING_TYPE); |
11 |
13 Sep 07 |
nicklas |
90 |
} |
11 |
13 Sep 07 |
nicklas |
91 |
|
11 |
13 Sep 07 |
nicklas |
/** The generic data item. */ |
11 |
13 Sep 07 |
nicklas |
93 |
private GenericData genericData; |
11 |
13 Sep 07 |
nicklas |
94 |
|
11 |
13 Sep 07 |
nicklas |
/** keep number of sequences from being read from the header all the time */ |
11 |
13 Sep 07 |
nicklas |
96 |
private int cachedNumSequences; |
11 |
13 Sep 07 |
nicklas |
97 |
|
11 |
13 Sep 07 |
nicklas |
/** chp data sets */ |
11 |
13 Sep 07 |
nicklas |
99 |
private DataSet entries; |
11 |
13 Sep 07 |
nicklas |
100 |
|
11 |
13 Sep 07 |
nicklas |
/** Clears the members. */ |
11 |
13 Sep 07 |
nicklas |
102 |
public void clear() { |
11 |
13 Sep 07 |
nicklas |
103 |
if (entries != null) |
11 |
13 Sep 07 |
nicklas |
104 |
{ |
11 |
13 Sep 07 |
nicklas |
105 |
entries.delete(); |
11 |
13 Sep 07 |
nicklas |
106 |
entries = null; |
11 |
13 Sep 07 |
nicklas |
107 |
} |
11 |
13 Sep 07 |
nicklas |
108 |
if (genericData != null) |
11 |
13 Sep 07 |
nicklas |
109 |
genericData.getHeader().clear(); |
11 |
13 Sep 07 |
nicklas |
110 |
cachedNumSequences = -1; |
11 |
13 Sep 07 |
nicklas |
111 |
} |
11 |
13 Sep 07 |
nicklas |
112 |
|
11 |
13 Sep 07 |
nicklas |
/** Sets the file name. |
11 |
13 Sep 07 |
nicklas |
* @param p The name of the CHP file |
11 |
13 Sep 07 |
nicklas |
115 |
*/ |
11 |
13 Sep 07 |
nicklas |
116 |
public void setFilename(String p) { |
11 |
13 Sep 07 |
nicklas |
117 |
genericData.getHeader().setFilename(p); |
11 |
13 Sep 07 |
nicklas |
118 |
} |
11 |
13 Sep 07 |
nicklas |
119 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the file name. |
11 |
13 Sep 07 |
nicklas |
* @return The file name. |
11 |
13 Sep 07 |
nicklas |
122 |
*/ |
11 |
13 Sep 07 |
nicklas |
123 |
public String getFilename() { |
11 |
13 Sep 07 |
nicklas |
124 |
return genericData.getHeader().getFilename(); |
11 |
13 Sep 07 |
nicklas |
125 |
} |
11 |
13 Sep 07 |
nicklas |
126 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the number of sequences. |
11 |
13 Sep 07 |
nicklas |
* @return The number of sequences. |
11 |
13 Sep 07 |
nicklas |
129 |
*/ |
11 |
13 Sep 07 |
nicklas |
130 |
public int getNumberSequences() { |
11 |
13 Sep 07 |
nicklas |
131 |
if (cachedNumSequences == -1) |
11 |
13 Sep 07 |
nicklas |
132 |
cachedNumSequences = getInt32FromGenericHdr(TILING_NUM_SEQS); |
11 |
13 Sep 07 |
nicklas |
133 |
return cachedNumSequences; |
11 |
13 Sep 07 |
nicklas |
134 |
} |
11 |
13 Sep 07 |
nicklas |
135 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the name of the algorithm. |
11 |
13 Sep 07 |
nicklas |
* @return The algorithm name. |
11 |
13 Sep 07 |
nicklas |
138 |
*/ |
11 |
13 Sep 07 |
nicklas |
139 |
public String getAlgName() { |
11 |
13 Sep 07 |
nicklas |
140 |
return getWStringFromGenericHdr(TILING_ALG_NAME); |
11 |
13 Sep 07 |
nicklas |
141 |
} |
11 |
13 Sep 07 |
nicklas |
142 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the algorithm version. |
11 |
13 Sep 07 |
nicklas |
* @return The version. |
11 |
13 Sep 07 |
nicklas |
145 |
*/ |
11 |
13 Sep 07 |
nicklas |
146 |
public String getAlgVersion() { |
11 |
13 Sep 07 |
nicklas |
147 |
return getWStringFromGenericHdr(TILING_ALG_VERSION); |
11 |
13 Sep 07 |
nicklas |
148 |
} |
11 |
13 Sep 07 |
nicklas |
149 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the algorithm parameters |
11 |
13 Sep 07 |
nicklas |
* @return The algoirhtm parameters. |
11 |
13 Sep 07 |
nicklas |
152 |
*/ |
11 |
13 Sep 07 |
nicklas |
153 |
public Vector /*ParameterNameValue*/ getAlgParams() { |
11 |
13 Sep 07 |
nicklas |
154 |
Vector params = new Vector(); |
11 |
13 Sep 07 |
nicklas |
155 |
GenericDataHeader hdr = genericData.getHeader().getGenericDataHdr(); |
11 |
13 Sep 07 |
nicklas |
156 |
Vector dataParams = hdr.getNameValParams(); |
11 |
13 Sep 07 |
nicklas |
157 |
for (int i=0; i<dataParams.size(); i++) |
11 |
13 Sep 07 |
nicklas |
158 |
{ |
11 |
13 Sep 07 |
nicklas |
159 |
ParameterNameValue param = (ParameterNameValue) dataParams.elementAt(i); |
11 |
13 Sep 07 |
nicklas |
160 |
String name = param.getName(); |
11 |
13 Sep 07 |
nicklas |
161 |
if (name.startsWith(TILING_PARAM_SUFFIX) == true) |
11 |
13 Sep 07 |
nicklas |
162 |
{ |
11 |
13 Sep 07 |
nicklas |
163 |
ParameterNameValue p = new ParameterNameValue(param); |
11 |
13 Sep 07 |
nicklas |
164 |
p.setName(name.substring(TILING_PARAM_SUFFIX.length(), name.length())); |
11 |
13 Sep 07 |
nicklas |
165 |
params.add(p); |
11 |
13 Sep 07 |
nicklas |
166 |
} |
11 |
13 Sep 07 |
nicklas |
167 |
} |
11 |
13 Sep 07 |
nicklas |
168 |
return params; |
11 |
13 Sep 07 |
nicklas |
169 |
} |
11 |
13 Sep 07 |
nicklas |
170 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the file header. |
11 |
13 Sep 07 |
nicklas |
* @return The file header. |
11 |
13 Sep 07 |
nicklas |
173 |
*/ |
11 |
13 Sep 07 |
nicklas |
174 |
public FileHeader getFileHeader() { return genericData.getHeader(); } |
11 |
13 Sep 07 |
nicklas |
175 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the generic data object. |
11 |
13 Sep 07 |
nicklas |
* @return The data object. |
11 |
13 Sep 07 |
nicklas |
178 |
*/ |
11 |
13 Sep 07 |
nicklas |
179 |
public GenericData getGenericData() { return genericData; } |
11 |
13 Sep 07 |
nicklas |
180 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the sequence data. |
11 |
13 Sep 07 |
nicklas |
* @return The data associated with the sequence. |
11 |
13 Sep 07 |
nicklas |
183 |
*/ |
11 |
13 Sep 07 |
nicklas |
184 |
public TilingSequenceData getTilingSequenceData() { |
11 |
13 Sep 07 |
nicklas |
185 |
TilingSequenceData data = new TilingSequenceData(); |
11 |
13 Sep 07 |
nicklas |
186 |
if (entries != null && entries.isOpen() == true) |
11 |
13 Sep 07 |
nicklas |
187 |
{ |
11 |
13 Sep 07 |
nicklas |
188 |
DataSetHeader hdr = entries.getHeader(); |
11 |
13 Sep 07 |
nicklas |
189 |
Vector params = hdr.getNameValParameters(); |
11 |
13 Sep 07 |
nicklas |
190 |
Vector dataParams = new Vector(); |
11 |
13 Sep 07 |
nicklas |
191 |
for (int i=0; i<params.size(); i++) |
11 |
13 Sep 07 |
nicklas |
192 |
{ |
11 |
13 Sep 07 |
nicklas |
193 |
ParameterNameValue param = (ParameterNameValue) params.elementAt(i); |
11 |
13 Sep 07 |
nicklas |
194 |
if (param.getName().compareTo(TILING_SEQ_NAME) == 0) |
11 |
13 Sep 07 |
nicklas |
195 |
{ |
11 |
13 Sep 07 |
nicklas |
196 |
data.setName(param.getValueText()); |
11 |
13 Sep 07 |
nicklas |
197 |
} |
11 |
13 Sep 07 |
nicklas |
198 |
else if (param.getName().compareTo(TILING_SEQ_GROUP_NAME) == 0) |
11 |
13 Sep 07 |
nicklas |
199 |
{ |
11 |
13 Sep 07 |
nicklas |
200 |
data.setGroupName(param.getValueText()); |
11 |
13 Sep 07 |
nicklas |
201 |
} |
11 |
13 Sep 07 |
nicklas |
202 |
else if (param.getName().compareTo(TILING_SEQ_VERSION) == 0) |
11 |
13 Sep 07 |
nicklas |
203 |
{ |
11 |
13 Sep 07 |
nicklas |
204 |
data.setVersion(param.getValueText()); |
11 |
13 Sep 07 |
nicklas |
205 |
} |
11 |
13 Sep 07 |
nicklas |
206 |
else |
11 |
13 Sep 07 |
nicklas |
207 |
{ |
11 |
13 Sep 07 |
nicklas |
208 |
dataParams.add(param); |
11 |
13 Sep 07 |
nicklas |
209 |
} |
11 |
13 Sep 07 |
nicklas |
210 |
} |
11 |
13 Sep 07 |
nicklas |
211 |
data.setParameters(dataParams); |
11 |
13 Sep 07 |
nicklas |
212 |
} |
11 |
13 Sep 07 |
nicklas |
213 |
return data; |
11 |
13 Sep 07 |
nicklas |
214 |
} |
11 |
13 Sep 07 |
nicklas |
215 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets the number of entries in a tiling sequence. |
11 |
13 Sep 07 |
nicklas |
* @param index The sequence index. |
11 |
13 Sep 07 |
nicklas |
* @return The number of entries in the sequence. |
11 |
13 Sep 07 |
nicklas |
219 |
*/ |
11 |
13 Sep 07 |
nicklas |
220 |
public int getTilingSequenceEntryCount(int index) { |
11 |
13 Sep 07 |
nicklas |
221 |
DataGroupHeader dcHdr = genericData.getHeader().getDataGroup(0); |
11 |
13 Sep 07 |
nicklas |
222 |
DataSetHeader dpHdr = dcHdr.getDataSet(index); |
11 |
13 Sep 07 |
nicklas |
223 |
return dpHdr.getRowCnt(); |
11 |
13 Sep 07 |
nicklas |
224 |
} |
11 |
13 Sep 07 |
nicklas |
225 |
|
11 |
13 Sep 07 |
nicklas |
/** Opens a group for reading. |
11 |
13 Sep 07 |
nicklas |
* @param index The index to the sequence. |
11 |
13 Sep 07 |
nicklas |
228 |
*/ |
11 |
13 Sep 07 |
nicklas |
229 |
public void openTilingSequenceDataSet(int index) { |
11 |
13 Sep 07 |
nicklas |
230 |
if (entries != null) |
11 |
13 Sep 07 |
nicklas |
231 |
entries.delete(); |
11 |
13 Sep 07 |
nicklas |
232 |
try |
11 |
13 Sep 07 |
nicklas |
233 |
{ |
11 |
13 Sep 07 |
nicklas |
234 |
entries = genericData.getDataSet(0, index); |
11 |
13 Sep 07 |
nicklas |
235 |
if (entries != null) |
11 |
13 Sep 07 |
nicklas |
236 |
entries.open(); |
11 |
13 Sep 07 |
nicklas |
237 |
} |
11 |
13 Sep 07 |
nicklas |
238 |
catch (Throwable t) |
11 |
13 Sep 07 |
nicklas |
239 |
{ |
11 |
13 Sep 07 |
nicklas |
240 |
} |
11 |
13 Sep 07 |
nicklas |
241 |
} |
11 |
13 Sep 07 |
nicklas |
242 |
|
11 |
13 Sep 07 |
nicklas |
/** Returns the entry for the given row. The data set must be open. |
11 |
13 Sep 07 |
nicklas |
* @param row The row index. |
11 |
13 Sep 07 |
nicklas |
* @return The entry. |
11 |
13 Sep 07 |
nicklas |
246 |
*/ |
11 |
13 Sep 07 |
nicklas |
247 |
public CHPTilingEntry getTilingSequenceEntry(int row) { |
11 |
13 Sep 07 |
nicklas |
248 |
if (entries != null && entries.isOpen() == true) |
11 |
13 Sep 07 |
nicklas |
249 |
{ |
11 |
13 Sep 07 |
nicklas |
250 |
CHPTilingEntry e = new CHPTilingEntry(); |
11 |
13 Sep 07 |
nicklas |
251 |
e.setPosition(entries.getDataInt(row, 0)); |
11 |
13 Sep 07 |
nicklas |
252 |
e.setValue(entries.getDataFloat(row, 1)); |
11 |
13 Sep 07 |
nicklas |
253 |
return e; |
11 |
13 Sep 07 |
nicklas |
254 |
} |
11 |
13 Sep 07 |
nicklas |
255 |
return null; |
11 |
13 Sep 07 |
nicklas |
256 |
} |
11 |
13 Sep 07 |
nicklas |
257 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets a parameter value as a String. |
11 |
13 Sep 07 |
nicklas |
* @param name The name of the parameter. |
11 |
13 Sep 07 |
nicklas |
* @return The String representation. |
11 |
13 Sep 07 |
nicklas |
261 |
*/ |
11 |
13 Sep 07 |
nicklas |
262 |
private String getWStringFromGenericHdr(String name) { |
11 |
13 Sep 07 |
nicklas |
263 |
String result=null; |
11 |
13 Sep 07 |
nicklas |
264 |
GenericDataHeader hdr = genericData.getHeader().getGenericDataHdr(); |
11 |
13 Sep 07 |
nicklas |
265 |
ParameterNameValue paramType = hdr.findNameValParam(name); |
11 |
13 Sep 07 |
nicklas |
266 |
if (paramType != null) |
11 |
13 Sep 07 |
nicklas |
267 |
{ |
11 |
13 Sep 07 |
nicklas |
268 |
result = paramType.getValueText(); |
11 |
13 Sep 07 |
nicklas |
269 |
} |
11 |
13 Sep 07 |
nicklas |
270 |
return result; |
11 |
13 Sep 07 |
nicklas |
271 |
} |
11 |
13 Sep 07 |
nicklas |
272 |
|
11 |
13 Sep 07 |
nicklas |
/** Gets a parameter value as an integer. |
11 |
13 Sep 07 |
nicklas |
* @param name The name of the parameter. |
11 |
13 Sep 07 |
nicklas |
* @return The integer representation. |
11 |
13 Sep 07 |
nicklas |
276 |
*/ |
11 |
13 Sep 07 |
nicklas |
277 |
private int getInt32FromGenericHdr(String name) { |
11 |
13 Sep 07 |
nicklas |
278 |
int result = 0; |
11 |
13 Sep 07 |
nicklas |
279 |
GenericDataHeader hdr = genericData.getHeader().getGenericDataHdr(); |
11 |
13 Sep 07 |
nicklas |
280 |
ParameterNameValue paramType = hdr.findNameValParam(name); |
11 |
13 Sep 07 |
nicklas |
281 |
if (paramType != null) |
11 |
13 Sep 07 |
nicklas |
282 |
{ |
11 |
13 Sep 07 |
nicklas |
283 |
result = paramType.getValueInt32(); |
11 |
13 Sep 07 |
nicklas |
284 |
} |
11 |
13 Sep 07 |
nicklas |
285 |
return result; |
11 |
13 Sep 07 |
nicklas |
286 |
} |
11 |
13 Sep 07 |
nicklas |
287 |
} |
11 |
13 Sep 07 |
nicklas |
288 |
|