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

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

References #1655: GUI improvements

  • Switch to PNG for some more icons.
  • Changed background and border colors to a brighter gray
  • Re-designed buttons again using a blue-ish border to indicate hovering.
  • Finalized the "Broadcast message" and "Reset filters" popups.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 15.8 KB
Line 
1<%-- $Id: parse_file.jsp 5903 2011-12-09 10:02:07Z 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
54<%
55request.setCharacterEncoding("UTF-8");
56final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
57final String ID = sc.getId();
58final DbControl dc = sc.newDbControl();
59final float scale = Base.getScale(sc);
60InputStream fileInputStream = null;
61try
62{
63  String path = request.getParameter("path");
64  String charsetName = Values.getString(request.getParameter("charset"), Config.getCharset());
65  PluginConfigurationRequest pcRequest = (PluginConfigurationRequest)sc.getSessionSetting("plugin.configure.request");
66  Plugin plugin = pcRequest.getPlugin();
67 
68  File file = null;
69  FlatFileParser parser = null;
70  FlatFileParser.LineType lastLine = null;
71  Pattern splitter = null;
72  boolean dataIsFound = false;
73  int maxLines = Values.getInt(request.getParameter("maxLines"), FlatFileParser.DEFAULT_MAX_UNKNOWN_LINES);
74 
75  List<String> messages = new ArrayList<String>();
76 
77  if (path != null)
78  {
79    Path p = new Path(path, Path.Type.FILE);
80    file = File.getByPath(dc, p, false);
81    parser = new FlatFileParser();
82    parser.setMaxUnknownLines(maxLines);
83   
84    String header = Values.getStringOrNull(request.getParameter("header"));
85    if (header != null)
86    {
87      try
88      {
89        parser.setHeaderRegexp(Pattern.compile(header));
90      }
91      catch (Throwable t)
92      {
93        messages.add("Invalid regular expression for header: " + HTML.encodeTags(header));
94      }
95    }
96   
97    String dataSplitter = Values.getStringOrNull(request.getParameter("dataSplitter"));
98    if (dataSplitter != null)
99    {
100      try
101      {
102        splitter = Pattern.compile(dataSplitter);
103        parser.setDataSplitterRegexp(splitter);
104      }
105      catch (Throwable t)
106      {
107        messages.add("Invalid regular expression for data splitter: " + HTML.encodeTags(dataSplitter));
108      }
109    }
110
111    String dataHeader = Values.getStringOrNull(request.getParameter("dataHeader"));
112    if (dataHeader != null)
113    {
114      try
115      {
116        parser.setDataHeaderRegexp(Pattern.compile(dataHeader));
117      }
118      catch (Throwable t)
119      {
120        messages.add("Invalid regular expression for data header: " + HTML.encodeTags(dataHeader));
121      }
122    }
123   
124    String dataFooter = Values.getStringOrNull(request.getParameter("dataFooter"));
125    if (dataFooter != null)
126    {
127      try
128      {
129        parser.setDataFooterRegexp(Pattern.compile(dataFooter));
130      }
131      catch (Throwable t)
132      {
133        messages.add("Invalid regular expression for data footer: " + HTML.encodeTags(dataFooter));
134      }
135    }
136   
137    String ignore = Values.getStringOrNull(request.getParameter("ignore"));
138    if (ignore != null)
139    {
140      try
141      {
142        parser.setIgnoreRegexp(Pattern.compile(ignore));
143      }
144      catch (Throwable t)
145      {
146        messages.add("Invalid regular expression for ignore: " + HTML.encodeTags(ignore));
147      }
148    }
149
150    parser.setTrimQuotes(Values.getBoolean(request.getParameter("trimQuotes")));
151    parser.setMinDataColumns(Values.getInt(request.getParameter("minDataColumns"), 0));
152    parser.setMaxDataColumns(Values.getInt(request.getParameter("maxDataColumns"), -1));
153   
154    fileInputStream = file.getDownloadStream(0);
155    if (plugin instanceof WrappedConfigureByExample)
156    {
157      WrappedConfigureByExample wex = (WrappedConfigureByExample)plugin;
158      fileInputStream = wex.wrapInputStream(fileInputStream);
159    }
160    parser.setInputStream(fileInputStream, charsetName);
161    lastLine = parser.parseHeaders();
162    dataIsFound = lastLine == FlatFileParser.LineType.DATA || lastLine == FlatFileParser.LineType.DATA_HEADER;
163    if (!dataIsFound)
164    {
165      messages.add("Start of data couldn't be found. Please try again with different settings.");
166    }
167  }
168  %>
169  <base:page type="popup" title="Test with file">
170  <base:head scripts="tabcontrol.js" styles="table.css,tabcontrol.css">
171    <script language="JavaScript">
172    var patterns = new Array();
173    var columnHeaders = new Array();
174    function setPattern(list, patternIndex)
175    {
176      var whatPattern = list[list.selectedIndex].value;
177      list.selectedIndex = 0;
178      var frm = window.parent.document.forms['testwithfile'];
179      if (frm[whatPattern])
180      {
181        frm[whatPattern].value = patterns[patternIndex];
182      }
183    }
184    function setColumnMapping(list, mappingName, expression, overwrite)
185    {
186      var frm = document.forms['mappings'];
187      var field = 'mapping.'+mappingName+'.expression';
188      if (list)
189      {
190        var colIndex = list[list.selectedIndex].value;
191        expression = columnHeaders.length > 0 ? columnHeaders[colIndex] : '\\';
192        list.selectedIndex = 0;
193        var style = Forms.getCheckedRadio(frm.expressionStyle);
194        var existing = overwrite ? '' : frm[field].value;
195        if (style && style.value == 1)
196        {
197          if (expression.indexOf('\\') >= 0) expression = colIndex;
198          expression = existing+'\\'+expression+'\\';
199        }
200        else
201        {
202          if (expression.indexOf('\\') >= 0)
203          {
204            expression = 'col('+colIndex+')';
205          }
206          else
207          {
208            expression = 'col(\''+expression+'\')';
209          }
210          if (existing)
211          {
212            expression = existing + '+' + expression;
213          }
214          else
215          {
216            expression = '=' + expression;
217          }
218        }
219      }
220     
221      frm[field].value = expression;
222      window.parent.setFormValue(field, expression);
223    }
224
225    var fuzzyMatches = new Array();
226    function setFuzzyMatches()
227    {
228      var frm = document.forms['mappings'];
229      var minScore = parseFloat(frm.similarity.value);
230      for (var i = 0; i < fuzzyMatches.length; i++)
231      {
232        var match = fuzzyMatches[i];
233        if (match)
234        {
235          if (match.score >= minScore)
236          {
237            var list = frm['list.' + match.name];
238            list.selectedIndex = 1 + match.fileColIndex;
239            setColumnMapping(list, match.name, '', true);
240          }
241          else
242          {
243            setColumnMapping(null, match.name, '', true);
244          }
245        }
246      }
247    }
248    </script>
249  </base:head>
250  <base:body onload="window.parent.adjustIFrameSize()" style="padding-left: 0px;">
251  <t:tabcontrol id="parsedFile" 
252    contentstyle="<%="height: "+(int)(scale*400)+"px;"%>" autoheight="false">
253  <t:tab
254    id="filedata"
255    title="File data"
256    >
257    <%
258    if (file == null)
259    {
260      %>
261      <br><br>
262      <div align="center">
263      <div class="error" style="width: 50%; font-size: larger; font-weight: bold;">
264        <br>
265        No file selected. Please select a file to test above.
266        <br><br>
267      </div>
268      </div>
269      <%
270    }
271    else
272    {
273      if (messages.size() > 0)
274      {
275        %>
276        <div class="error">
277        <table align="center"><tr><td>
278        <b>Could not parse the file <code><%=HTML.encodeTags(path)%></code></b>
279        <ol>
280        <li><%=Values.getString(messages, "<li>", true)%>
281        </ol>
282        </td></tr></table>
283        </div>
284        <%
285      }
286      %>
287      <table class="itemlist" border="0" cellspacing="0" cellpadding="0" style="padding-right: 1px;">
288      <tr>
289        <td class="data">
290        <table border="0" cellspacing="0" cellpadding="0">
291       
292        <tr>
293          <th class="columnheader">Line</th>
294          <th class="columnheader">Columns</th>
295          <th class="columnheader">Type</th>
296          <th class="columnheader">Use as</th>
297          <th class="columnheader" colspan="99">File data</th>
298        </tr>
299     
300        <%
301        int currentLine = 0;
302        int headerLines = parser.getLineCount();
303        String[] rowclass = new String[] { "oddrow", "evenrow" };
304        int rowClassIndex = 0;
305        List<String> patterns = new ArrayList<String>(maxLines);
306        while (currentLine <= maxLines && currentLine < headerLines)
307        {
308          FlatFileParser.Line line = parser.getLine(currentLine);
309          patterns.add(HTML.javaScriptEncode(Pattern.quote(line.line())));
310          String[] data = null;
311          if (line.type() == FlatFileParser.LineType.HEADER)
312          {
313            data = new String[] { line.name(), line.value() };
314          }
315          else if (splitter != null)
316          {
317            data = parser.trimQuotes(splitter.split(line.line(), 99));
318          }
319          else
320          {
321            data = new String[] { line.line() };
322          }
323          %>
324          <tr class="<%=rowclass[rowClassIndex]%>">
325            <td class="cell"><%=line.lineNo()%></td>
326            <td class="cell"><%=data.length%></td>
327            <td class="cell"><%=line.type()%></td>
328            <td class="cell">
329              <select onchange="setPattern(this, <%=currentLine%>)">
330              <option value="">
331              <option value="dataHeader">Data header
332              <option value="dataFooter">Data footer
333              </select>
334            </td>
335            <%
336            for (String d : data)
337            {
338              %>
339              <td class="cell"><%=HTML.encodeTags(d) %></td>
340              <%
341            }
342            %>
343          </tr>
344          <%
345          currentLine++;
346          rowClassIndex = 1 - rowClassIndex;
347        }
348        if (currentLine < maxLines)
349        {
350          if (lastLine == FlatFileParser.LineType.DATA) parser.nextData();
351          while (currentLine <= maxLines && parser.hasMoreData())
352          {
353            FlatFileParser.Data data = parser.nextData();
354            patterns.add(HTML.javaScriptEncode(Pattern.quote(data.line())));
355            if (parser.getNumSkippedLines() > 0)
356            {
357              %>
358              <tr>
359                <td class="error" colspan="99">
360                Skipped <%=parser.getNumSkippedLines()%> lines
361                (<%=parser.getIgnoredLines()%> ignored; <%=parser.getUnknownLines()%> unknown)
362                </td>
363              </tr>
364              <%
365            }
366            %>
367            <tr class="<%=rowclass[rowClassIndex]%>">
368              <td class="cell"><%=data.lineNo()%></td>
369              <td class="cell"><%=data.columns()%></td>
370              <td class="cell">Data</td>
371              <td class="cell">
372                <select onchange="setPattern(this, <%=currentLine%>)">
373                <option value="">
374                <option value="dataHeader">Data header
375                <option value="dataFooter">Data footer
376                </select>
377              </td>
378              <%
379              for (int i = 0; i < data.columns(); ++i)
380              {
381                %>
382                <td class="cell"><%=HTML.encodeTags(data.get(i))%></td>
383                <%
384              }
385              %>
386            </tr>
387            <%
388            currentLine++;
389            rowClassIndex = 1 - rowClassIndex;
390          }
391          if (parser.getNumSkippedLines() > 0)
392          {
393            %>
394            <tr>
395              <td class="error" colspan="99">
396              Skipped <%=parser.getNumSkippedLines()%> lines
397              (<%=parser.getIgnoredLines()%> ignored; <%=parser.getUnknownLines()%> unknown)
398              </td>
399            </tr>
400            <%
401          }
402        }
403        %>
404        <script language="JavaScript">
405        <%
406        for (String pattern : patterns)
407        {
408          %>
409          patterns[patterns.length] = '<%=pattern%>';
410          <%
411        }
412        if (parser.getColumnHeaders() != null)
413        {
414          for (String columnHeader : parser.getColumnHeaders())
415          {
416            %>
417            columnHeaders[columnHeaders.length] = '<%=HTML.javaScriptEncode(columnHeader)%>';
418            <%
419          }
420        }
421        %>
422        </script>
423        </table>
424        </td>
425      </tr>
426      </table>
427      <%
428    }
429    %>
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      <table>
495      <tr>
496      <td>
497      <b>Mapping style:</b>
498      <input type="radio" name="expressionStyle" id="expressionStyleSimple" value="1" checked><label for="expressionStyleSimple">Simple</label>
499      <input type="radio" name="expressionStyle" id="expressionStyleExpression" value="2"><label for="expressionStyleExpression">Expression</label>
500      </td>
501      <%
502      if (matches != null)
503      {
504        %>
505        <td>
506        <base:button onclick="setFuzzyMatches()" title="Auto generate" 
507          tooltip="Generate mappings by finding the best match between Property and File column"/>
508        </td>
509        <td>
510          Similarity score: <input type="text" 
511          name="similarity" value="0.85" onkeypress="return Numbers.numberOnly(event)">
512          (0 = bad; 1 = good)
513        </td>
514        <%
515      }
516      %>
517      </tr>
518      </table>
519
520      <table class="itemlist" border="0" cellspacing="0" cellpadding="0">
521      <tr>
522        <td class="data">
523        <table border="0" cellspacing="0" cellpadding="0">
524        <tr>
525          <th class="columnheader">Property</th>
526          <th class="columnheader">Mapping expression</th>
527          <th class="columnheader">File columns</th>
528        </tr>
529        <%
530        for (String name : mappingParameters)
531        {
532          %>
533          <tr>
534            <td class="cell"><%=HTML.encodeTags(request.getParameter("mapping." + name + ".label"))%></td>
535            <td class="cell">
536              <input type="text" class="text" name="mapping.<%=name%>.expression"
537                size="40" maxlength="80" 
538                value="<%=HTML.encodeTags(request.getParameter("mapping." + name + ".expression"))%>"
539                onblur="setColumnMapping(null, '<%=name%>', this.value)">
540               
541                <base:icon image="cancel.png" 
542                  onclick="<%="setColumnMapping(null, '" + name + "', '')"%>" 
543                  tooltip="Clear this expression"/>
544            </td>
545            <td class="cell">
546              <select name="list.<%=name%>" onchange="setColumnMapping(this, '<%=name%>')">
547              <option value="">
548              <%=mappings%>
549              </select>
550            </td>
551          </tr>
552          <%
553        }
554        %>
555        </table>
556        </td>
557      </tr>
558      </table>
559      </form>
560    </t:tab>
561     
562    </t:tabcontrol>
563  </base:body>
564  </base:page>
565  <%
566}
567finally
568{
569  if (fileInputStream != null) fileInputStream.close();
570  if (dc != null) dc.close();
571}
572%>
573
Note: See TracBrowser for help on using the repository browser.