1 package org.lcsim.lcio;
2
3 import hep.io.sio.SIOOutputStream;
4 import hep.io.sio.SIOWriter;
5 import java.io.File;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.util.Collection;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14 import java.util.logging.Logger;
15 import org.lcsim.event.EventHeader;
16 import org.lcsim.event.EventHeader.LCMetaData;
17
18
19
20
21
22
23
24
25
26
27
28
29
30 public class LCIOWriter
31 {
32 private final static Logger log = Logger.getLogger(LCIOWriter.class.getName());
33 private SIOWriter writer;
34 private final HandlerManager manager = HandlerManager.instance();
35 private int lastRunNumber = -1;
36 private String lastDetectorName = "";
37 private Set<String> ignore = new HashSet<String>();
38 private Set<String> only = new HashSet<String>();
39 private File file;
40
41
42
43
44
45 public LCIOWriter(File file) throws IOException
46 {
47 this.file = file;
48 reOpen();
49 }
50
51
52
53
54
55 public LCIOWriter(String file) throws IOException
56 {
57 this(new File(file));
58 }
59
60
61
62
63
64
65 public LCIOWriter(File file, Collection<String> ignoreCollections) throws IOException
66 {
67 this(file);
68 this.ignore = new HashSet(ignoreCollections);
69 }
70
71
72
73
74
75
76 public LCIOWriter(String file, Collection<String> ignoreCollections) throws IOException
77 {
78 this(file);
79 this.ignore = new HashSet(ignoreCollections);
80 }
81
82
83
84
85
86 public void addIgnore(String collection)
87 {
88 ignore.add(collection);
89 }
90
91 public void addAllIgnore(Collection<String> collections)
92 {
93 ignore.addAll(collections);
94 }
95
96
97
98
99
100 public void removeIgnore(String collection)
101 {
102 ignore.remove(collection);
103 }
104
105
106 public void clearIgnore()
107 {
108 ignore.clear();
109 }
110
111
112
113
114 public void addWriteOnly(String collection)
115 {
116 only.add(collection);
117 }
118
119 public void addAllWriteOnly(Collection<String> collections)
120 {
121 only.addAll(collections);
122 }
123
124
125
126
127
128 public void removeWriteOnly(String collection)
129 {
130 only.remove(collection);
131 }
132
133
134
135 public void clearWriteOnly()
136 {
137 only.clear();
138 }
139
140 public void close() throws IOException
141 {
142 writer.close();
143 writer = null;
144 }
145
146 public void flush() throws IOException
147 {
148 writer.flush();
149 }
150
151 public void reOpen() throws IOException
152 {
153 if (writer == null)
154 {
155 writer = new SIOWriter(new FileOutputStream(file));
156 }
157
158
159 lastRunNumber = -1;
160 }
161
162 private void writeData(EventHeader event, boolean headerOnly) throws IOException
163 {
164 if (headerOnly)
165 {
166 SIOOutputStream out = writer.createBlock(LCIOConstants.eventHeaderBlockName, LCIOConstants.MAJORVERSION, LCIOConstants.MINORVERSION);
167 out.writeInt(event.getRunNumber());
168 out.writeInt(event.getEventNumber());
169 out.writeLong(event.getTimeStamp());
170 out.writeString(event.getDetectorName());
171
172 Map<String,String> blocks = new HashMap<String,String>();
173 List<List<Object>> collections = event.get(Object.class);
174 for (List<Object> collection : collections)
175 {
176 LCMetaData md = event.getMetaData(collection);
177 if (LCIOUtil.bitTest(md.getFlags(),LCIOConstants.BITTransient)) continue;
178 else if (!only.isEmpty() && !only.contains(md.getName())) continue;
179 else if (ignore.contains(md.getName())) continue;
180 else
181 {
182 Class type = md.getType();
183 LCIOBlockHandler bh = manager.handlerForClass(type,md.getFlags());
184 if (bh == null) {
185
186 }
187 else
188 {
189 if (!isValidCollectionName(md.getName())) throw new IOException("Collection name "+md.getName()+" is invalid for LCIO");
190 blocks.put(md.getName(),bh.getType());
191 }
192 }
193 }
194
195 out.writeInt(blocks.size());
196 for (Map.Entry<String,String> entry : blocks.entrySet() )
197 {
198 out.writeString(entry.getKey());
199 out.writeString(entry.getValue());
200 }
201 Map<String,int[]> intMap = event.getIntegerParameters();
202 Map<String,float[]> floatMap = event.getFloatParameters();
203 Map<String,String[]> stringMap = event.getStringParameters();
204 SIOLCParameters.write(intMap,floatMap,stringMap,out);
205 out.close();
206 }
207 else
208 {
209 List<List<Object>> collections = event.get(Object.class);
210 for (List<Object> collection : collections)
211 {
212 LCMetaData md = event.getMetaData(collection);
213
214 if (LCIOUtil.bitTest(md.getFlags(),LCIOConstants.BITTransient)) continue;
215 else if (!only.isEmpty() && !only.contains(md.getName())) continue;
216 else if (ignore.contains(md.getName())) continue;
217 else
218 {
219 LCIOBlockHandler bh = manager.handlerForClass(md.getType(),md.getFlags());
220 if (bh != null) bh.writeBlock(writer,collection,md);
221 }
222 }
223 }
224 }
225
226 private void writeData(LCIORunHeader header) throws IOException
227 {
228 SIOOutputStream out = writer.createBlock(LCIOConstants.runBlockName, LCIOConstants.MAJORVERSION, LCIOConstants.MINORVERSION);
229 out.writeInt(header.getRunNumber());
230 out.writeString(header.getDetectorName());
231 out.writeString(header.getDescription());
232 String[] active = header.getActiveSubdetectors();
233 out.writeInt(active.length);
234 for (int i=0; i<active.length; i++) out.writeString(active[i]);
235 Map<String,int[]> intMap = header.getIntegerParameters();
236 Map<String,float[]> floatMap = header.getFloatParameters();
237 Map<String,String[]> stringMap = header.getStringParameters();
238 SIOLCParameters.write(intMap,floatMap,stringMap,out);
239 out.close();
240 }
241
242 public void write(EventHeader event) throws IOException
243 {
244 if (event.getRunNumber() != lastRunNumber || !lastDetectorName.equals(event.getDetectorName()))
245 {
246 lastRunNumber = event.getRunNumber();
247 lastDetectorName = event.getDetectorName();
248 if (lastDetectorName == null) lastDetectorName = "";
249 write(new DefaultRunHeader(lastRunNumber,lastDetectorName,new SIOLCParameters()));
250 }
251 writer.createRecord(LCIOConstants.eventHeaderRecordName,true);
252 writeData(event,true);
253 writer.createRecord(LCIOConstants.eventRecordName,true);
254 writeData(event,false);
255 }
256
257 public void write(LCIORunHeader header) throws IOException
258 {
259 writer.createRecord(LCIOConstants.runRecordName,true);
260 writeData(header);
261 }
262
263 private static class DefaultRunHeader implements LCIORunHeader
264 {
265 private final int run;
266 private final String name;
267 private final static String[] noDetectors = new String[0];
268 private SIOLCParameters runParameters;
269 DefaultRunHeader(int run, String name, SIOLCParameters runParameters)
270 {
271 this.run = run;
272 this.name = name;
273 this.runParameters = runParameters;
274 }
275
276 public String[] getActiveSubdetectors()
277 {
278 return noDetectors;
279 }
280
281 public String getDescription()
282 {
283 return "";
284 }
285
286 public String getDetectorName()
287 {
288 return name;
289 }
290
291 public int getRunNumber()
292 {
293 return run;
294 }
295
296 public Map<String, float[]> getFloatParameters()
297 {
298 return runParameters.getFloatMap();
299 }
300
301 public Map<String, int[]> getIntegerParameters()
302 {
303 return runParameters.getIntMap();
304 }
305
306 public Map<String, String[]> getStringParameters()
307 {
308 return runParameters.getStringMap();
309 }
310 }
311
312 private boolean isValidCollectionName(String name)
313 {
314 int len = name.length() ;
315 if(name.length()==0) return false ;
316 char c0 = name.charAt(0) ;
317 if (!Character.isLetter(c0) && c0 != '_') return false;
318
319 for (int i=1; i< len; i++)
320 {
321 char c = name.charAt(i) ;
322 if (!Character.isLetterOrDigit(c0) && c != '_' ) return false ;
323 }
324 return true ;
325 }
326 }