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

Last change on this file since 5955 was 5955, checked in by Nicklas Nordborg, 10 years ago

References #1655: GUI improvements

"Test with file" dialog.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 15.9 KB
Line 
1<%-- $Id: parse_file.jsp 5955 2012-02-13 14:36:42Z 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 pageEncoding="UTF-8" session="false"
27  contentType="text/html; charset=UTF-8" 
28  import="net.sf.basedb.core.SessionControl"
29  import="net.sf.basedb.core.DbControl"
30  import="net.sf.basedb.core.Config"
31  import="net.sf.basedb.core.Item"
32  import="net.sf.basedb.core.File"
33  import="net.sf.basedb.core.Path"
34  import="net.sf.basedb.core.Location"
35  import="net.sf.basedb.core.PluginConfigurationRequest"
36  import="net.sf.basedb.core.plugin.Plugin"
37  import="net.sf.basedb.util.parser.FlatFileParser"
38  import="net.sf.basedb.util.parser.WrappedConfigureByExample"
39  import="net.sf.basedb.clients.web.Base"
40  import="net.sf.basedb.util.Values"
41  import="net.sf.basedb.util.fuzzy.StringMatcher"
42  import="net.sf.basedb.util.fuzzy.StringMatcher.FuzzyMatch"
43  import="net.sf.basedb.clients.web.util.HTML"
44  import="java.util.regex.Pattern"
45  import="java.util.List"
46  import="java.util.ArrayList"
47  import="java.util.Set"
48  import="java.io.InputStream"
49%>
50<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
51<%@ taglib prefix="m" uri="/WEB-INF/menu.tld" %>
52<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
53<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
54
55<%
56request.setCharacterEncoding("UTF-8");
57final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
58final String ID = sc.getId();
59final DbControl dc = sc.newDbControl();
60final float scale = Base.getScale(sc);
61InputStream fileInputStream = null;
62try
63{
64  String path = request.getParameter("path");
65  String charsetName = Values.getString(request.getParameter("charset"), Config.getCharset());
66  PluginConfigurationRequest pcRequest = (PluginConfigurationRequest)sc.getSessionSetting("plugin.configure.request");
67  Plugin plugin = pcRequest.getPlugin();
68 
69  File file = null;
70  FlatFileParser parser = null;
71  FlatFileParser.LineType lastLine = null;
72  Pattern splitter = null;
73  boolean dataIsFound = false;
74  int maxLines = Values.getInt(request.getParameter("maxLines"), FlatFileParser.DEFAULT_MAX_UNKNOWN_LINES);
75 
76  List<String> messages = new ArrayList<String>();
77 
78  if (path != null)
79  {
80    Path p = new Path(path, Path.Type.FILE);
81    file = File.getByPath(dc, p, false);
82    parser = new FlatFileParser();
83    parser.setMaxUnknownLines(maxLines);
84   
85    String header = Values.getStringOrNull(request.getParameter("header"));
86    if (header != null)
87    {
88      try
89      {
90        parser.setHeaderRegexp(Pattern.compile(header));
91      }
92      catch (Throwable t)
93      {
94        messages.add("Invalid regular expression for header: " + HTML.encodeTags(header));
95      }
96    }
97   
98    String dataSplitter = Values.getStringOrNull(request.getParameter("dataSplitter"));
99    if (dataSplitter != null)
100    {
101      try
102      {
103        splitter = Pattern.compile(dataSplitter);
104        parser.setDataSplitterRegexp(splitter);
105      }
106      catch (Throwable t)
107      {
108        messages.add("Invalid regular expression for data splitter: " + HTML.encodeTags(dataSplitter));
109      }
110    }
111
112    String dataHeader = Values.getStringOrNull(request.getParameter("dataHeader"));
113    if (dataHeader != null)
114    {
115      try
116      {
117        parser.setDataHeaderRegexp(Pattern.compile(dataHeader));
118      }
119      catch (Throwable t)
120      {
121        messages.add("Invalid regular expression for data header: " + HTML.encodeTags(dataHeader));
122      }
123    }
124   
125    String dataFooter = Values.getStringOrNull(request.getParameter("dataFooter"));
126    if (dataFooter != null)
127    {
128      try
129      {
130        parser.setDataFooterRegexp(Pattern.compile(dataFooter));
131      }
132      catch (Throwable t)
133      {
134        messages.add("Invalid regular expression for data footer: " + HTML.encodeTags(dataFooter));
135      }
136    }
137   
138    String ignore = Values.getStringOrNull(request.getParameter("ignore"));
139    if (ignore != null)
140    {
141      try
142      {
143        parser.setIgnoreRegexp(Pattern.compile(ignore));
144      }
145      catch (Throwable t)
146      {
147        messages.add("Invalid regular expression for ignore: " + HTML.encodeTags(ignore));
148      }
149    }
150
151    parser.setTrimQuotes(Values.getBoolean(request.getParameter("trimQuotes")));
152    parser.setMinDataColumns(Values.getInt(request.getParameter("minDataColumns"), 0));
153    parser.setMaxDataColumns(Values.getInt(request.getParameter("maxDataColumns"), -1));
154   
155    fileInputStream = file.getDownloadStream(0);
156    if (plugin instanceof WrappedConfigureByExample)
157    {
158      WrappedConfigureByExample wex = (WrappedConfigureByExample)plugin;
159      fileInputStream = wex.wrapInputStream(fileInputStream);
160    }
161    parser.setInputStream(fileInputStream, charsetName);
162    lastLine = parser.parseHeaders();
163    dataIsFound = lastLine == FlatFileParser.LineType.DATA || lastLine == FlatFileParser.LineType.DATA_HEADER;
164    if (!dataIsFound)
165    {
166      messages.add("Start of data couldn't be found. Please try again with different settings.");
167    }
168  }
169  %>
170  <base:page type="iframe" title="Test with file">
171  <base:head scripts="tabcontrol.js" styles="table.css,tabcontrol.css">
172    <script language="JavaScript">
173    var patterns = new Array();
174    var columnHeaders = new Array();
175    function setPattern(list, patternIndex)
176    {
177      var whatPattern = list[list.selectedIndex].value;
178      list.selectedIndex = 0;
179      var frm = window.parent.document.forms['testwithfile'];
180      if (frm[whatPattern])
181      {
182        frm[whatPattern].value = patterns[patternIndex];
183      }
184    }
185    function setColumnMapping(list, mappingName, expression, overwrite)
186    {
187      var frm = document.forms['mappings'];
188      var field = 'mapping.'+mappingName+'.expression';
189      if (list)
190      {
191        var colIndex = list[list.selectedIndex].value;
192        expression = columnHeaders.length > 0 ? columnHeaders[colIndex] : '\\';
193        list.selectedIndex = 0;
194        var style = Forms.getCheckedRadio(frm.expressionStyle);
195        var existing = overwrite ? '' : frm[field].value;
196        if (style && style.value == 1)
197        {
198          if (expression.indexOf('\\') >= 0) expression = colIndex;
199          expression = existing+'\\'+expression+'\\';
200        }
201        else
202        {
203          if (expression.indexOf('\\') >= 0)
204          {
205            expression = 'col('+colIndex+')';
206          }
207          else
208          {
209            expression = 'col(\''+expression+'\')';
210          }
211          if (existing)
212          {
213            expression = existing + '+' + expression;
214          }
215          else
216          {
217            expression = '=' + expression;
218          }
219        }
220      }
221     
222      frm[field].value = expression;
223      window.parent.setFormValue(field, expression);
224    }
225
226    var fuzzyMatches = new Array();
227    function setFuzzyMatches()
228    {
229      var frm = document.forms['mappings'];
230      var minScore = parseFloat(frm.similarity.value);
231      for (var i = 0; i < fuzzyMatches.length; i++)
232      {
233        var match = fuzzyMatches[i];
234        if (match)
235        {
236          if (match.score >= minScore)
237          {
238            var list = frm['list.' + match.name];
239            list.selectedIndex = 1 + match.fileColIndex;
240            setColumnMapping(list, match.name, '', true);
241          }
242          else
243          {
244            setColumnMapping(null, match.name, '', true);
245          }
246        }
247      }
248    }
249    </script>
250  </base:head>
251  <base:body>
252  <t:tabcontrol 
253    id="parsedFile"
254    subclass="absolutefull dialogtabcontrol bottomborder"
255    position="top"
256    >
257  <t:tab
258    id="filedata"
259    title="File data"
260    >
261    <div style="padding-top: 0.5em;">
262    <%
263    if (file == null)
264    {
265      %>
266      <div class="messagecontainer error" style="margin-top: 0px;">
267        No file selected. Please select a file to test above.
268      </div>
269      <%
270    }
271    else
272    {
273      if (messages.size() > 0)
274      {
275        %>
276        <div class="messagecontainer error">
277        <b>Could not parse the file <code><%=HTML.encodeTags(path)%></code></b>
278        <ol>
279        <li><%=Values.getString(messages, "<li>", true)%>
280        </ol>
281        </div>
282        <%
283      }
284      %>
285      <div class="itemlist fulltable">
286        <div class="data" style="top: 0px; margin-top:0px;">
287        <table>
288          <thead>
289          <tr>
290            <th>Line</th>
291            <th>Columns</th>
292            <th>Type</th>
293            <th>Use as</th>
294            <th colspan="99">File data</th>
295          </tr>
296          </thead>
297          <tbody class="rows">
298     
299        <%
300        int currentLine = 0;
301        int headerLines = parser.getLineCount();
302        String[] rowclass = new String[] { "oddrow", "evenrow" };
303        int rowClassIndex = 0;
304        List<String> patterns = new ArrayList<String>(maxLines);
305        while (currentLine <= maxLines && currentLine < headerLines)
306        {
307          FlatFileParser.Line line = parser.getLine(currentLine);
308          patterns.add(HTML.javaScriptEncode(Pattern.quote(line.line())));
309          String[] data = null;
310          if (line.type() == FlatFileParser.LineType.HEADER)
311          {
312            data = new String[] { line.name(), line.value() };
313          }
314          else if (splitter != null)
315          {
316            data = parser.trimQuotes(splitter.split(line.line(), 99));
317          }
318          else
319          {
320            data = new String[] { line.line() };
321          }
322          %>
323          <tr class="<%=rowclass[rowClassIndex]%> highlight">
324            <td class="cell"><%=line.lineNo()%></td>
325            <td class="cell"><%=data.length%></td>
326            <td class="cell"><%=line.type()%></td>
327            <td class="cell">
328              <select onchange="setPattern(this, <%=currentLine%>)">
329              <option value="">
330              <option value="dataHeader">Data header
331              <option value="dataFooter">Data footer
332              </select>
333            </td>
334            <%
335            for (String d : data)
336            {
337              %>
338              <td class="cell"><%=HTML.encodeTags(d) %></td>
339              <%
340            }
341            %>
342          </tr>
343          <%
344          currentLine++;
345          rowClassIndex = 1 - rowClassIndex;
346        }
347        if (currentLine < maxLines)
348        {
349          if (lastLine == FlatFileParser.LineType.DATA) parser.nextData();
350          while (currentLine <= maxLines && parser.hasMoreData())
351          {
352            FlatFileParser.Data data = parser.nextData();
353            patterns.add(HTML.javaScriptEncode(Pattern.quote(data.line())));
354            if (parser.getNumSkippedLines() > 0)
355            {
356              %>
357              <tr>
358                <td class="error" colspan="99">
359                Skipped <%=parser.getNumSkippedLines()%> lines
360                (<%=parser.getIgnoredLines()%> ignored; <%=parser.getUnknownLines()%> unknown)
361                </td>
362              </tr>
363              <%
364            }
365            %>
366            <tr class="<%=rowclass[rowClassIndex]%>">
367              <td class="cell"><%=data.lineNo()%></td>
368              <td class="cell"><%=data.columns()%></td>
369              <td class="cell">Data</td>
370              <td class="cell">
371                <select onchange="setPattern(this, <%=currentLine%>)">
372                <option value="">
373                <option value="dataHeader">Data header
374                <option value="dataFooter">Data footer
375                </select>
376              </td>
377              <%
378              for (int i = 0; i < data.columns(); ++i)
379              {
380                %>
381                <td class="cell"><%=HTML.encodeTags(data.get(i))%></td>
382                <%
383              }
384              %>
385            </tr>
386            <%
387            currentLine++;
388            rowClassIndex = 1 - rowClassIndex;
389          }
390          if (parser.getNumSkippedLines() > 0)
391          {
392            %>
393            <tr>
394              <td class="error" colspan="99">
395              Skipped <%=parser.getNumSkippedLines()%> lines
396              (<%=parser.getIgnoredLines()%> ignored; <%=parser.getUnknownLines()%> unknown)
397              </td>
398            </tr>
399            <%
400          }
401        }
402        %>
403        </tbody>
404        </table>
405        <script language="JavaScript">
406        <%
407        for (String pattern : patterns)
408        {
409          %>
410          patterns[patterns.length] = '<%=pattern%>';
411          <%
412        }
413        if (parser.getColumnHeaders() != null)
414        {
415          for (String columnHeader : parser.getColumnHeaders())
416          {
417            %>
418            columnHeaders[columnHeaders.length] = '<%=HTML.javaScriptEncode(columnHeader)%>';
419            <%
420          }
421        }
422        %>
423        </script>
424      </div>
425      </div>
426      <%
427    }
428    %>
429      </div>
430    </t:tab>
431
432    <t:tab
433      id="mappings"
434      title="Column mappings"
435      visible="<%=dataIsFound && request.getParameter("mappingParameterNames") != null%>"
436      >
437      <%
438      StringBuilder sb = new StringBuilder();
439      List<String> headers = parser.getColumnHeaders();
440      int index = 0;
441      if (headers != null)
442      {
443        for (String header : headers)
444        {
445          sb.append("<option value=\"" + index + "\">" + HTML.encodeTags(header));
446          index++;
447        }
448      }
449      else
450      {
451        int maxDataColumns = Values.getInt(request.getParameter("maxDataColumns"), -1);
452        while (index < maxDataColumns)
453        {
454          sb.append("<option value=\"" + index + "\">" + index);
455          index++;
456        }
457      }
458      String mappings = sb.toString();
459      String[] mappingParameters = request.getParameter("mappingParameterNames").split(",");
460      List<String> labels = new ArrayList<String>();
461      for (String name : mappingParameters)
462      {
463        labels.add(request.getParameter("mapping." + name + ".label"));
464      }
465      StringMatcher sm = new StringMatcher();
466      List<FuzzyMatch> matches = headers == null ? null : sm.getBestPairs(labels, headers);
467      %>
468      <script language="JavaScript">
469      <%
470      if (matches != null)
471      {
472        int i = 0;
473        for (FuzzyMatch fm : matches)
474        {
475          String name = mappingParameters[i];
476          if (fm != null)
477          {
478            %>
479            fuzzyMatches[<%=i%>] = { name:'<%=name%>', fileColIndex:<%=headers.indexOf(fm.getValue())%>, score:<%=fm.getScore()%> }; 
480            <%
481          }
482          else
483          {
484            %>
485            fuzzyMatches[<%=i%>] = null;
486            <%
487          }
488          ++i;
489        }
490      }
491      %>
492      </script>
493      <form name="mappings">
494      <div class="absolutefull" style="height: 2em;">
495        <table>
496        <tr>
497          <td style="padding-left: 2px;">
498            <b>Mapping style:</b>
499            <input type="radio" name="expressionStyle" id="expressionStyleSimple" value="1" checked><label for="expressionStyleSimple">Simple</label>
500            <input type="radio" name="expressionStyle" id="expressionStyleExpression" value="2"><label for="expressionStyleExpression">Expression</label>
501          </td>
502          <%
503          if (matches != null)
504          {
505            %>
506            <td style="padding-left: 4px;">
507            <base:button onclick="setFuzzyMatches()" title="Auto generate" 
508              tooltip="Generate mappings by finding the best match between Property and File column"/>
509            </td>
510            <td style="padding-left: 4px; width: 50%;">
511              Similarity score: <input type="text" 
512              name="similarity" value="0.85" onkeypress="return Numbers.numberOnly(event)">
513              (0 = bad; 1 = good)
514            </td>
515            <%
516          }
517          %>
518        </tr>
519        </table>
520      </div>
521     
522      <div class="absolutefull topborder" style="top: 2em;">
523
524        <table class="fullform input100">
525        <tbody class="sectionheader">
526          <tr>
527            <th class="rightborder">Property</th>
528            <th class="rightborder">Mapping expression</th>
529            <th>File columns</th>
530          </tr>
531        </tbody>
532        <%
533        for (String name : mappingParameters)
534        {
535          %>
536          <tr>
537            <th><%=HTML.encodeTags(request.getParameter("mapping." + name + ".label"))%></th>
538            <td class="cell">
539              <table style="width: 100%;">
540              <tr>
541                <td>
542                <input type="text" class="text" name="mapping.<%=name%>.expression"
543                  maxlength="80" 
544                  value="<%=HTML.encodeTags(request.getParameter("mapping." + name + ".expression"))%>"
545                  onblur="setColumnMapping(null, '<%=name%>', this.value)">
546                </td>
547              <td style="width: 22px;">
548                <base:icon image="cancel.png" 
549                  onclick="<%="setColumnMapping(null, '" + name + "', '')"%>" 
550                  tooltip="Clear this expression"/>
551              </td>
552              </tr>
553              </table>
554            </td>
555            <td class="cell" style="width: 15em;">
556              <select name="list.<%=name%>" onchange="setColumnMapping(this, '<%=name%>')">
557              <option value="">
558              <%=mappings%>
559              </select>
560            </td>
561          </tr>
562          <%
563        }
564        %>
565        <tr class="dynamic">
566          <th></th>
567          <td></td>
568          <td></td>
569        </tr>
570        </table>
571      </div>
572    </form>
573    </t:tab>
574     
575    </t:tabcontrol>
576  </base:body>
577  </base:page>
578  <%
579}
580finally
581{
582  if (fileInputStream != null) fileInputStream.close();
583  if (dc != null) dc.close();
584}
585%>
586
Note: See TracBrowser for help on using the repository browser.