View Javadoc

1   package uk.ac.cam.spectra.spectrasub;
2   
3   import java.io.File;
4   import java.io.FileInputStream;
5   import java.io.FileOutputStream;
6   import java.io.IOException;
7   import java.io.InputStream;
8   import java.io.OutputStream;
9   import java.util.HashMap;
10  import java.util.Map;
11  
12  import nu.xom.Document;
13  
14  import org.apache.commons.io.IOUtils;
15  import org.apache.log4j.Logger;
16  
17  import uk.ac.cam.spectra.CMLType;
18  import uk.ac.cam.spectra.Combine;
19  import uk.ac.cam.spectra.DataFileException;
20  import uk.ac.cam.spectra.DataProcess;
21  import uk.ac.cam.spectra.Validation;
22  import uk.ac.cam.spectra.lniclient.LNI;
23  
24  /**
25   * Stateless object containing logic for handling processes. Methods here denote
26   * transactions.
27   * 
28   * @author ojd20
29   */
30  public class DataPackageManager {
31  
32      private static final Logger LOG = Logger
33              .getLogger(DataPackageManager.class);
34  
35      /**
36       * Set by IoC
37       */
38      private DataPackageDAO pkgDao;
39  
40      /**
41       * Set by IoC
42       */
43      private CMLType cmlType;
44  
45      /**
46       * Set by IoC
47       */
48      private Packager packager;
49  
50      /**
51       * Set by IoC
52       */
53      private Depositor depositor;
54  
55      private LNI lni;
56  
57      public CMLType getCmlType() {
58          return cmlType;
59      }
60  
61      public void setCmlType(CMLType cmlType) {
62          this.cmlType = cmlType;
63      }
64  
65      public DataPackageDAO getDataPackageDao() {
66          return pkgDao;
67      }
68  
69      public void setDataPackageDao(DataPackageDAO dao) {
70          this.pkgDao = dao;
71      }
72  
73      /**
74       * Saves data from an input stream into the next upload slot of the
75       * referenced package, performs validation, metadata extraction and any
76       * necessary file conversions.
77       * 
78       * @param packageId
79       * @param in
80       * @param name
81       * @return
82       * @throws NotFoundException
83       */
84      public DataFile nextData(String packageId, InputStream in, String name)
85              throws NotFoundException {
86          DataPackage pkg = pkgDao.load(packageId);
87          DataFile df = pkg.getNextUpload();
88          LOG.debug("Adding data for " + df);
89          File data = pkgDao.createDataFileHandle(pkg);
90          OutputStream out = null;
91          try {
92              out = new FileOutputStream(data);
93              IOUtils.copy(in, out);
94          } catch (IOException e) {
95              LOG.error("Problem writing data to package: " + e.getMessage(), e);
96              throw new RuntimeException("Problem writing data to package: "
97                      + e.getMessage(), e);
98          } finally {
99              IOUtils.closeQuietly(in);
100             IOUtils.closeQuietly(out);
101         }
102         df.setFile(data);
103         df.setFileName(name);
104         pkg.doneNext();
105         DataProcess dp = new DataProcess();
106         dp.setPerformConversion(df.getConvert());
107         dp.setPerformExtraction(df.getExtractMetadata());
108         dp.setPerformValidation(true);
109         dp.setSourceFile(df.getFile());
110         dp.setMetadataPackageUri(pkg.getNormalizedURIString());
111 
112         try {
113             df.getDataFileType().process(dp);
114         } catch (DataFileException e) {
115             LOG.warn("Converting DataFileException to a validation error");
116             Validation v = dp.getValidation();
117             if (v != null) {
118                 v.getErrors().add(e.getMessage());
119             }
120         }
121         if(dp.getValidation()==null) {
122             dp.setValidation(new Validation());
123         }
124         Validation v= dp.getValidation();
125         df.setValidation(v);
126         LOG.debug(df + " has " + v.getErrors().size() + " errors");
127         if (!v.hasErrors()) {
128             if (df.getExtractMetadata()) {
129                 LOG.debug("Extracting metadata");
130                 pkg.addMetadata(dp.getExtractedMetadata(), df.getCombine());
131             }
132             if (df.getConvert()) {
133                 Document cml = dp.getConvertedCml();
134                 if (cml != null) {
135                     if (pkg.getCmlFile() == null) {
136                         DataFile cdf = new DataFile();
137                         cdf.setDataFileType(getCmlType());
138                         cdf.setFileName(df.getDataFileType().convertName(
139                                 df.getFileName()));
140                         cdf.setFile(pkgDao.createDataFileHandle(pkg));
141                         LOG.debug("Setting CML file to " + cdf);
142                         pkg.setCmlFile(cdf);
143                     }
144                     pkg.append(cml);
145                     // Mainly to extract the InChI
146                     LOG.debug("Extracting metadata from CML ");
147                     DataProcess dp2 = new DataProcess();
148                     dp2.setSourceFile(pkg.getCmlFile().getFile());
149                     dp2.setPerformExtraction(true);
150                     dp2.setMetadataPackageUri(pkg.getNormalizedURIString());
151                     pkg.getCmlFile().getDataFileType().process(dp2);
152                     pkg
153                             .addMetadata(dp2.getExtractedMetadata(),
154                                     Combine.combine);
155                 }
156             }
157         }
158         LOG.debug("Saving: " + packageId);
159         pkgDao.save(pkg);
160         return df;
161     }
162 
163     /**
164      * Sealing the package prepares the package for submission to the
165      * repository.
166      * 
167      * @param p
168      */
169     public void buildPackage(DataPackage p) {
170         LOG.debug("packaging " + p);
171         // Create a working folder for the zip file
172         File pDir = pkgDao.getPackagingDirectory(p.getId(), true);
173 
174         // Copy the data files across
175         Map<DataFile, File> destinations = new HashMap<DataFile, File>(10);
176         for (DataFile df : p.getAddedDataFiles()) {
177             File dest = new File(pDir, df.getFileName());
178             try {
179                 dest.createNewFile();
180                 destinations.put(df, dest);
181                 FileInputStream in = null;
182                 FileOutputStream out = null;
183                 try {
184                     in = new FileInputStream(df.getFile());
185                     out = new FileOutputStream(dest);
186                     IOUtils.copy(in, out);
187                 } finally {
188                     IOUtils.closeQuietly(in);
189                     IOUtils.closeQuietly(out);
190                 }
191             } catch (IOException e) {
192                 LOG.error("Problem copying data files into packaging dir: "
193                         + e.getMessage(), e);
194                 throw new RuntimeException(
195                         "Problem copying data files into packaging dir: "
196                                 + e.getMessage(), e);
197             }
198         }
199 
200         // Copy the CML file across
201         DataFile cmlFile = p.getCmlFile();
202         LOG.debug("CML file (Shouldn't be null!): " + cmlFile + " name: "
203                 + cmlFile.getFileName());
204         LOG.debug("Package dir: " + pDir);
205         File dest = new File(pDir, cmlFile.getFileName());
206         try {
207             dest.createNewFile();
208             destinations.put(cmlFile, dest);
209             FileInputStream in = null;
210             FileOutputStream out = null;
211             try {
212                 in = new FileInputStream(cmlFile.getFile());
213                 out = new FileOutputStream(dest);
214                 IOUtils.copy(in, out);
215             } finally {
216                 IOUtils.closeQuietly(in);
217                 IOUtils.closeQuietly(out);
218             }
219         } catch (IOException e) {
220             LOG.error("Problem copying CML into packaging dir: "
221                     + e.getMessage(), e);
222             throw new RuntimeException(
223                     "Problem copying data files into packaging dir: "
224                             + e.getMessage(), e);
225         }
226 
227         // Transcode the metadata and serialize into the new packager
228         File mf = new File(pDir, packager.getManifestName(p));
229         try {
230             mf.createNewFile();
231             packager.transcodeAndSerialize(p, mf);
232         } catch (IOException e) {
233             LOG.error("Problem writing metadata into packaging dir: "
234                     + e.getMessage(), e);
235             throw new RuntimeException(
236                     "Problem writing metadata into packaging dir: "
237                             + e.getMessage(), e);
238         }
239 
240     }
241 
242     public Packager getPackager() {
243         return packager;
244     }
245 
246     public void setPackager(Packager pkger) {
247         this.packager = pkger;
248     }
249 
250     /**
251      * @param packageId
252      * @return a URL for the item.
253      * @throws NotFoundException
254      */
255     public String packAndGo(String packageId) throws NotFoundException {
256         return depositor.deposit(packageId);
257     }
258 
259     public LNI getLni() {
260         return lni;
261     }
262 
263     public void setLni(LNI lni) {
264         this.lni = lni;
265     }
266 
267     public Depositor getDepositor() {
268         return depositor;
269     }
270 
271     public void setDepositor(Depositor depositor) {
272         this.depositor = depositor;
273     }
274 
275 }