source: trunk/www/common/plugin/parse_file.jsp @ 6684

Last change on this file since 6684 was 6684, checked in by Nicklas Nordborg, 9 years ago

Merge changes between 3.4-beta-1 to 3.4.0 to the trunk.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 15.1 KB
Line 
1<%-- $Id: parse_file.jsp 6684 2015-01-14 13:29:04Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2006 Johan Enell, Nicklas Nordborg
4  Copyright (C) 2007 Nicklas Nordborg
5
6  This file is part of BASE - BioArray Software Environment.
7  Available at http://base.thep.lu.se/
8
9  BASE is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License
11  as published by the Free Software Foundation; either version 3
12  of the License, or (at your option) any later version.
13
14  BASE is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with BASE. If not, see <http://www.gnu.org/licenses/>.
21  ------------------------------------------------------------------
22
23  @author Nicklas
24  @version 2.0
25--%>
26<%@page import="org.json.simple.JSONObject"%>
27<%@ page pageEncoding="UTF-8" session="false"
28  contentType="text/html; charset=UTF-8" 
29  import="net.sf.basedb.core.SessionControl"
30  import="net.sf.basedb.core.DbControl"
31  import="net.sf.basedb.core.Config"
32  import="net.sf.basedb.core.Item"
33  import="net.sf.basedb.core.File"
34  import="net.sf.basedb.core.Path"
35  import="net.sf.basedb.core.Location"
36  import="net.sf.basedb.core.PluginConfigurationRequest"
37  import="net.sf.basedb.core.plugin.Plugin"
38  import="net.sf.basedb.util.parser.FlatFileParser"
39  import="net.sf.basedb.util.parser.WrappedConfigureByExample"
40  import="net.sf.basedb.clients.web.Base"
41  import="net.sf.basedb.util.Values"
42  import="net.sf.basedb.util.fuzzy.StringMatcher"
43  import="net.sf.basedb.util.fuzzy.StringMatcher.FuzzyMatch"
44  import="net.sf.basedb.clients.web.util.HTML"
45  import="java.util.regex.Pattern"
46  import="java.util.List"
47  import="java.util.ArrayList"
48  import="java.util.Set"
49  import="java.io.InputStream"
50  import="org.json.simple.JSONArray"
51%>
52<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
53<%@ taglib prefix="m" uri="/WEB-INF/menu.tld" %>
54<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
55<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
56
57<%
58request.setCharacterEncoding("UTF-8");
59final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
60final String ID = sc.getId();
61final DbControl dc = sc.newDbControl();
62final float scale = Base.getScale(sc);
63InputStream fileInputStream = null;
64try
65{
66  String path = request.getParameter("path");
67  String charsetName = Values.getString(request.getParameter("charset"), Config.getCharset());
68  PluginConfigurationRequest pcRequest = (PluginConfigurationRequest)sc.getSessionSetting("plugin.configure.request");
69  Plugin plugin = pcRequest.getPlugin();
70 
71  File file = null;
72  FlatFileParser parser = null;
73  FlatFileParser.LineType lastLine = null;
74  Pattern splitter = null;
75  boolean dataIsFound = false;
76  int maxLines = Values.getInt(request.getParameter("maxLines"), FlatFileParser.DEFAULT_MAX_UNKNOWN_LINES);
77 
78  List<String> messages = new ArrayList<String>();
79  JSONArray linePatterns = new JSONArray();
80  JSONArray jsonFuzzy = new JSONArray();
81 
82  if (path != null)
83  {
84    Path p = new Path(path, Path.Type.FILE);
85    file = File.getByPath(dc, p, false);
86    parser = new FlatFileParser();
87    parser.setMaxUnknownLines(maxLines);
88   
89    String header = Values.getStringOrNull(request.getParameter("header"));
90    if (header != null)
91    {
92      try
93      {
94        parser.setHeaderRegexp(Pattern.compile(header));
95      }
96      catch (Throwable t)
97      {
98        messages.add("Invalid regular expression for header: " + HTML.encodeTags(header));
99      }
100    }
101   
102    String dataSplitter = Values.getStringOrNull(request.getParameter("dataSplitter"));
103    if (dataSplitter != null)
104    {
105      try
106      {
107        splitter = Pattern.compile(dataSplitter);
108        parser.setDataSplitterRegexp(splitter);
109      }
110      catch (Throwable t)
111      {
112        messages.add("Invalid regular expression for data splitter: " + HTML.encodeTags(dataSplitter));
113      }
114    }
115
116    String dataHeader = Values.getStringOrNull(request.getParameter("dataHeader"));
117    if (dataHeader != null)
118    {
119      try
120      {
121        parser.setDataHeaderRegexp(Pattern.compile(dataHeader));
122      }
123      catch (Throwable t)
124      {
125        messages.add("Invalid regular expression for data header: " + HTML.encodeTags(dataHeader));
126      }
127    }
128   
129    String dataFooter = Values.getStringOrNull(request.getParameter("dataFooter"));
130    if (dataFooter != null)
131    {
132      try
133      {
134        parser.setDataFooterRegexp(Pattern.compile(dataFooter));
135      }
136      catch (Throwable t)
137      {
138        messages.add("Invalid regular expression for data footer: " + HTML.encodeTags(dataFooter));
139      }
140    }
141   
142    String ignore = Values.getStringOrNull(request.getParameter("ignore"));
143    if (ignore != null)
144    {
145      try
146      {
147        parser.setIgnoreRegexp(Pattern.compile(ignore));
148      }
149      catch (Throwable t)
150      {
151        messages.add("Invalid regular expression for ignore: " + HTML.encodeTags(ignore));
152      }
153    }
154
155    parser.setTrimQuotes(Values.getBoolean(request.getParameter("trimQuotes")));
156    parser.setMinDataColumns(Values.getInt(request.getParameter("minDataColumns"), 0));
157    parser.setMaxDataColumns(Values.getInt(request.getParameter("maxDataColumns"), -1));
158   
159    fileInputStream = file.getDownloadStream(0);
160    if (plugin instanceof WrappedConfigureByExample)
161    {
162      WrappedConfigureByExample wex = (WrappedConfigureByExample)plugin;
163      fileInputStream = wex.wrapInputStream(fileInputStream);
164    }
165    parser.setInputStream(fileInputStream, charsetName);
166    lastLine = parser.parseHeaders();
167    dataIsFound = lastLine == FlatFileParser.LineType.DATA || lastLine == FlatFileParser.LineType.DATA_HEADER;
168    if (!dataIsFound)
169    {
170      messages.add("Start of data couldn't be found. Please try again with different settings.");
171    }
172  }
173  %>
174  <base:page type="iframe" title="Test with file">
175  <base:head scripts="tabcontrol-2.js,~parse_file.js" styles="table.css,tabcontrol.css" />
176  <base:body>
177  <div class="absolutefull bottomborder">
178
179  <t:tabcontrol 
180    id="parsedFile"
181    subclass="absolutefull dialogtabcontrol"
182    position="top" active="filedata"
183    >
184  <t:tab
185    id="filedata"
186    title="File data"
187    >
188   
189    <%
190    if (file == null)
191    {
192      %>
193      <div class="absolutefull bg-filled-50">
194      <div class="messagecontainer error">
195        No file selected. Please select a file to test above.
196      </div>
197      </div>
198      <%
199    }
200    else
201    {
202      if (messages.size() > 0)
203      {
204        %>
205        <div class="bg-filled-50" style="padding: 5px;">
206        <div class="messagecontainer error" style="margin: 0;">
207        <b>Could not parse the file <code><%=HTML.encodeTags(path)%></code></b>
208        <ol>
209        <li><%=Values.getString(messages, "<li>", true)%>
210        </ol>
211        </div>
212        </div>
213        <%
214      }
215      %>
216      <div class="itemlist" style="<%=messages.size()==0 ? "" : "border-top-width: 1px;"%>">
217        <div class="data">
218        <table style="border: 0;">
219          <thead class="bg-filled-100">
220          <tr>
221            <th>Line</th>
222            <th>Columns</th>
223            <th>Type</th>
224            <th>Use as</th>
225            <th colspan="99">File data</th>
226          </tr>
227          </thead>
228          <tbody class="rows">
229     
230        <%
231        int currentLine = 0;
232        int headerLines = parser.getLineCount();
233        String[] rowclass = new String[] { "bg-oddrow", "bg-evenrow" };
234        int rowClassIndex = 0;
235
236        while (currentLine <= maxLines && currentLine < headerLines)
237        {
238          FlatFileParser.Line line = parser.getLine(currentLine);
239          linePatterns.add(Pattern.quote(line.line()));
240          String[] data = null;
241          if (line.type() == FlatFileParser.LineType.HEADER)
242          {
243            data = new String[] { line.name(), line.value() };
244          }
245          else if (splitter != null)
246          {
247            data = parser.trimQuotes(splitter.split(line.line(), 99));
248          }
249          else
250          {
251            data = new String[] { line.line() };
252          }
253          %>
254          <tr class="<%=rowclass[rowClassIndex]%> highlight">
255            <td class="cell"><%=line.lineNo()%></td>
256            <td class="cell"><%=data.length%></td>
257            <td class="cell"><%=line.type()%></td>
258            <td class="cell">
259              <select class="auto-init" 
260                data-auto-init="line-pattern"
261                data-line-no="<%=currentLine%>">
262              <option value="">
263              <option value="dataHeader">Data header
264              <option value="dataFooter">Data footer
265              </select>
266            </td>
267            <%
268            int colNo = 0;
269            for (String d : data)
270            {
271              %>
272              <td class="cell"><%=HTML.encodeTags(d) %></td>
273              <%
274              colNo++;
275              if (colNo == 99) break;
276            }
277            if (colNo < 99)
278            {
279              %>
280              <td class="cell" colspan="<%=99-colNo%>"></td>
281              <%
282            }
283            %>
284          </tr>
285          <%
286          currentLine++;
287          rowClassIndex = 1 - rowClassIndex;
288        }
289        if (currentLine < maxLines)
290        {
291          if (lastLine == FlatFileParser.LineType.DATA) parser.nextData();
292          while (currentLine <= maxLines && parser.hasMoreData())
293          {
294            FlatFileParser.Data data = parser.nextData();
295            linePatterns.add(Pattern.quote(data.line()));
296            if (parser.getNumSkippedLines() > 0)
297            {
298              %>
299              <tr>
300                <td class="error" colspan="103">
301                Skipped <%=parser.getNumSkippedLines()%> lines
302                (<%=parser.getIgnoredLines()%> ignored; <%=parser.getUnknownLines()%> unknown)
303                </td>
304              </tr>
305              <%
306            }
307            %>
308            <tr class="<%=rowclass[rowClassIndex]%> highlight">
309              <td class="cell"><%=data.lineNo()%></td>
310              <td class="cell"><%=data.columns()%></td>
311              <td class="cell">Data</td>
312              <td class="cell">
313                <select class="auto-init" 
314                  data-auto-init="line-pattern"
315                  data-line-no="<%=currentLine%>">
316                <option value="">
317                <option value="dataHeader">Data header
318                <option value="dataFooter">Data footer
319                </select>
320              </td>
321              <%
322              for (int i = 0; i < data.columns(); ++i)
323              {
324                %>
325                <td class="cell"><%=HTML.encodeTags(data.get(i))%></td>
326                <%
327              }
328              if (data.columns() < 99)
329              {
330                %>
331                <td class="cell" colspan="<%=99-data.columns()%>"></td>
332                <%
333              }
334              %>
335            </tr>
336            <%
337            currentLine++;
338            rowClassIndex = 1 - rowClassIndex;
339          }
340          if (parser.getNumSkippedLines() > 0)
341          {
342            %>
343            <tr>
344              <td class="error" colspan="99">
345              Skipped <%=parser.getNumSkippedLines()%> lines
346              (<%=parser.getIgnoredLines()%> ignored; <%=parser.getUnknownLines()%> unknown)
347              </td>
348            </tr>
349            <%
350          }
351        }
352        %>
353        </tbody>
354        </table>
355      </div>
356      </div>
357      <%
358    }
359    %>
360    </t:tab>
361
362    <t:tab
363      id="mappings"
364      title="Column mappings"
365      visible="<%=dataIsFound && request.getParameter("mappingParameterNames") != null%>"
366      >
367      <%
368      StringBuilder sb = new StringBuilder();
369      List<String> headers = parser.getColumnHeaders();
370      int index = 0;
371      if (headers != null)
372      {
373        for (String header : headers)
374        {
375          sb.append("<option value=\"" + index + "\">" + HTML.encodeTags(header));
376          index++;
377        }
378      }
379      else
380      {
381        int maxDataColumns = Values.getInt(request.getParameter("maxDataColumns"), -1);
382        while (index < maxDataColumns)
383        {
384          sb.append("<option value=\"" + index + "\">" + index);
385          index++;
386        }
387      }
388      String mappings = sb.toString();
389      String[] mappingParameters = request.getParameter("mappingParameterNames").split(",");
390      if (headers != null)
391      {
392        List<String> labels = new ArrayList<String>();
393        for (String name : mappingParameters)
394        {
395          labels.add(request.getParameter("mapping." + name + ".label"));
396        }
397        StringMatcher sm = new StringMatcher();
398        List<FuzzyMatch> matches = sm.getBestPairs(labels, headers);
399        int i = 0;
400        for (FuzzyMatch fm : matches)
401        {
402          String name = mappingParameters[i];
403          if (fm != null)
404          {
405            JSONObject jsonFuzzyMatch = new JSONObject();
406            jsonFuzzyMatch.put("name", mappingParameters[i]);
407            jsonFuzzyMatch.put("columnIndex", headers.indexOf(fm.getValue()));
408            jsonFuzzyMatch.put("score", fm.getScore());
409            jsonFuzzy.add(jsonFuzzyMatch);
410          }
411          else
412          {
413            jsonFuzzy.add(null);
414          }
415          ++i;
416        }
417      }
418      %>
419      <form name="mappings">
420      <div class="absolutefull bg-filled-100" style="height: 2em;">
421        <table>
422        <tr>
423          <td style="padding-left: 4px;">
424            <b>Mapping style:</b>
425            <input type="radio" name="expressionStyle" id="expressionStyleSimple" value="1" checked><label for="expressionStyleSimple">Simple</label>
426            <input type="radio" name="expressionStyle" id="expressionStyleExpression" value="2"><label for="expressionStyleExpression">Expression</label>
427          </td>
428          <%
429          if (jsonFuzzy.size() > 0)
430          {
431            %>
432            <td style="padding-left: 4px;">
433            <base:button id="btnFuzzyMatches" title="Auto generate" 
434              tooltip="Generate mappings by finding the best match between Property and File column"/>
435            </td>
436            <td style="padding-left: 4px; width: 50%;">
437              Similarity score:
438              <input type="text" id="similarityScore" name="similarity" value="0.85">
439              (0 = bad; 1 = good)
440            </td>
441            <%
442          }
443          %>
444        </tr>
445        </table>
446      </div>
447     
448      <div class="absolutefull input100" style="top: 2em;">
449
450        <tbl:table id="col-mappings">
451          <tbl:columndef 
452            id="property"
453            title="Property"
454          />
455          <tbl:columndef 
456            id="expression"
457            title="Mapping expression"
458          />
459          <tbl:columndef 
460            id="columns"
461            title="File columns"
462          />
463          <tbl:data>
464            <tbl:headers>
465              <tbl:headerrow>
466                <tbl:columnheaders />
467              </tbl:headerrow>
468            </tbl:headers>           
469            <tbl:rows>
470            <%
471            for (String name : mappingParameters)
472            {
473              %>
474              <tbl:row>
475                <tbl:cell column="property"><%=HTML.encodeTags(request.getParameter("mapping." + name + ".label"))%></tbl:cell>
476                <tbl:cell column="expression">
477               
478                    <table style="width: 100%;">
479                    <tr>
480                      <td>
481                      <input type="text" class="text auto-init" data-auto-init="column-mapping"
482                        name="mapping.<%=name%>.expression"
483                        maxlength="80" 
484                        value="<%=HTML.encodeTags(request.getParameter("mapping." + name + ".expression"))%>">
485                      </td>
486                    <td style="width: 22px;">
487                      <base:icon image="cancel.png" subclass="auto-init" id="<%="clear."+name %>"
488                        data-auto-init="column-mapping-clear" data-mapping="<%=name%>"
489                        tooltip="Clear this expression"/>
490                    </td>
491                    </tr>
492                    </table>
493                </tbl:cell>
494               
495                <tbl:cell column="columns">
496                  <select name="list.<%=name%>" class="auto-init"
497                    data-auto-init="column-mapping-preset" data-mapping="<%=name%>">
498                  <option value="">
499                  <%=mappings%>
500                  </select>
501                </tbl:cell>
502             
503              </tbl:row>
504              <%
505            }
506            %>
507            </tbl:rows>
508          </tbl:data>
509        </tbl:table>
510      </div>
511    </form>
512    </t:tab>
513     
514    </t:tabcontrol>
515   
516      <div id="page-data" class="datacontainer"
517        data-line-patterns="<%=HTML.encodeTags(linePatterns.toJSONString())%>"
518        <%
519        if (parser != null && parser.getColumnHeaders() != null)
520        {
521          %>
522          data-column-headers="<%=HTML.encodeTags(JSONArray.toJSONString(parser.getColumnHeaders())) %>"
523          <%
524        }
525        %>
526        data-fuzzy-matches="<%=HTML.encodeTags(jsonFuzzy.toJSONString()) %>"
527        ></div>
528    </div>
529  </base:body>
530  </base:page>
531  <%
532}
533finally
534{
535  if (fileInputStream != null) fileInputStream.close();
536  if (dc != null) dc.close();
537}
538%>
539
Note: See TracBrowser for help on using the repository browser.