Java tutorial
/** * Copyright 2014 CMBI (contact: <Coos.Baakman@radboudumc.nl>) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package nl.ru.cmbi.vase.web.page; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringBufferInputStream; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.zip.GZIPInputStream; import nl.ru.cmbi.vase.analysis.Calculator; import nl.ru.cmbi.vase.analysis.MutationDataObject; import nl.ru.cmbi.vase.data.VASEDataObject; import nl.ru.cmbi.vase.data.VASEDataObject.PlotDescription; import nl.ru.cmbi.vase.data.stockholm.Alignment; import nl.ru.cmbi.vase.data.stockholm.AlignmentSet; import nl.ru.cmbi.vase.data.stockholm.ResidueInfo; import nl.ru.cmbi.vase.data.stockholm.ResidueInfoSet; import nl.ru.cmbi.vase.parse.StockholmParser; import nl.ru.cmbi.vase.parse.VASEXMLParser; import nl.ru.cmbi.vase.tools.util.Config; import nl.ru.cmbi.vase.tools.util.Utils; import nl.ru.cmbi.vase.web.WicketApplication; import nl.ru.cmbi.vase.web.panel.align.AlignmentDisplayPanel; import nl.ru.cmbi.vase.web.panel.align.AlignmentLinkedPlotPanel; import nl.ru.cmbi.vase.web.panel.align.AlignmentTablePanel; import nl.ru.cmbi.vase.web.panel.align.StructurePanel; import nl.ru.cmbi.vase.web.rest.JobRestResource; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.io.IOUtils; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.RestartResponseAtInterceptPageException; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.repeater.RepeatingView; import org.apache.wicket.model.IModel; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.protocol.http.RequestUtils; import org.apache.wicket.request.Url; import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.util.string.StringValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.core.util.string.JavaScriptUtils; public class AlignmentPage extends BasePage { private static final Logger log = LoggerFactory.getLogger(AlignmentPage.class); private String structureID; private Character chainID = null; public AlignmentPage(final PageParameters parameters) { log.info("start AlignmentPage with parameters " + parameters.toString()); StringValue structureIDString = parameters.get(0), chainIDString = parameters.get(1); if (structureIDString == null || structureIDString.isNull() || structureIDString.isEmpty()) { throw new RestartResponseAtInterceptPageException(new ErrorPage("structure id missing")); } else { structureID = structureIDString.toString().toLowerCase(); if (chainIDString != null && !chainIDString.isNull() && !chainIDString.isEmpty()) { chainID = chainIDString.toChar(); } try { File xmlFile = new File(Config.getCacheDir(), structureID + ".xml"), gzXmlFile = new File(Config.getCacheDir(), structureID + ".xml.gz"); if (xmlFile.isFile()) { VASEDataObject data = VASEXMLParser.parse(new FileInputStream(xmlFile)); this.initPageWith(data); } else if (gzXmlFile.isFile()) { VASEDataObject data = VASEXMLParser.parse(new GZIPInputStream(new FileInputStream(xmlFile))); this.initPageWith(data); } else { if (Config.isXmlOnly()) { throw new RestartResponseAtInterceptPageException(new ErrorPage( "VASE is running in xml-only mode, so only xml-entries can be accessed. (see homepage)")); } InputStream pdbIn = Utils.getPdbInputStream(structureID); if (pdbIn == null) { throw new RestartResponseAtInterceptPageException( new ErrorPage("Unable to resolve PDB URL for: " + structureID)); } InputStream stockholmInputStream = Utils.getStockholmInputStream(structureID); if (stockholmInputStream == null) { throw new RestartResponseAtInterceptPageException( new ErrorPage("No alignment data for: " + structureID)); } Set<Character> stockholmChainIDs = StockholmParser.listChainsInStockholm(stockholmInputStream); if (chainID == null) { if (stockholmChainIDs.size() == 1) { // no chain id needs to be given, since there's only one chainID = stockholmChainIDs.iterator().next(); } else { // Redirect to a page with chain selection PageParameters params = new PageParameters(); params.add(SearchResultsPage.parameterName, structureID); this.setResponsePage(SearchResultsPage.class, params); return; } } else if (!stockholmChainIDs.contains(chainID)) { throw new RestartResponseAtInterceptPageException( new ErrorPage("No such chain in " + structureID + ": " + chainID)); } stockholmInputStream = Utils.getStockholmInputStream(structureID); VASEDataObject data = StockholmParser.parseStockHolm(stockholmInputStream, pdbIn, structureID, chainID); if (data == null) log.error("data is null"); this.initPageWith(data); } } catch (RestartResponseAtInterceptPageException e) { //just rethrow it throw e; } catch (Exception e) { // any other type of exception log.error("Error getting alignments for " + structureIDString + " : " + e.getMessage(), e); throw new RestartResponseAtInterceptPageException( new ErrorPage("Error getting alignments for " + structureIDString + " : " + e.toString())); } } } private void initPageWith(final VASEDataObject data) { setPageTitle(data.getTitle()); add(new Label("alignment-header", data.getTitle())); final AlignmentDisplayPanel alignmentPanel = new AlignmentDisplayPanel("alignment", data); add(alignmentPanel); add(new JSDefinitions("js-definitions", alignmentPanel)); final RepeatingView tabs = new RepeatingView("tabs"); addToTabs("data-table", "Table", new AlignmentTablePanel("data-table", alignmentPanel, data), tabs); add(new ListView<PlotDescription>("plots", data.getPlots()) { private int plotCount = 0; @Override protected void populateItem(ListItem<PlotDescription> item) { PlotDescription pd = item.getModelObject(); plotCount++; Component plot = new AlignmentLinkedPlotPanel("plot", alignmentPanel, pd, data.getTable()); String id = "plot" + plotCount; // must be unique addToTabs(id, pd.getPlotTitle(), plot, tabs); item.add(plot); } }); add(tabs); String structurePath = Utils.getPDBPath(data.getPdbID()); add(new StructurePanel("structure", structurePath, data)); } private List<String> tabids = new ArrayList<String>(); private void addToTabs(String id, String tabTitle, Component component, RepeatingView tabs) { // first added becomes the active tab String display = "none"; boolean bActive = false; if (tabids.size() == 0) { bActive = true; display = "block"; } tabids.add(id); component.add(new AttributeModifier("id", id)); component.add(new AttributeAppender("style", new Model("display:" + display), ";")); add(component); tabs.add(new TabFragment(tabs.newChildId(), id, tabTitle, bActive)); } public class TabFragment extends Fragment { public TabFragment(String id, String tabid, String title, boolean startActive) { super(id, "tab-fragment", AlignmentPage.this); add(new AttributeModifier("id", "switch-" + tabid)); WebMarkupContainer link = new WebMarkupContainer("tab-link"); link.add(new AttributeModifier("onclick", String.format("switchTabVisibility('%s');", tabid))); link.add(new Label("tab-title", title)); if (startActive) { add(new AttributeAppender("class", new Model("active"), " ")); } add(link); } } private class JSDefinitions extends Component { private AlignmentDisplayPanel alignmentPanel; public JSDefinitions(String id, AlignmentDisplayPanel a) { super(id); alignmentPanel = a; } @Override protected void onRender() { JavaScriptUtils.writeOpenTag(getResponse()); ////////////////////////////////////////////////// getResponse().write("var tabids=["); for (String tabid : AlignmentPage.this.tabids) { getResponse().write(String.format("\'%s\',", tabid)); } getResponse().write("];\n"); String urlString = RequestCycle.get().getUrlRenderer() .renderFullUrl(Url.parse(RequestCycle.get().urlFor(this.getApplication().getHomePage(), null))); //getResponse().write(String.format("var baseURL='%s';\n", urlString)); getResponse().write("var pdbResiduePrefix=\"" + AlignmentDisplayPanel.pdbResiduePrefix + "\";\n"); getResponse().write("var pPDBresclass=/" + AlignmentDisplayPanel.pdbResiduePrefix + "([^\\s]+)/;\n"); getResponse().write( "var palignmentposclass=/" + AlignmentDisplayPanel.alignmentPositionPrefix + "([0-9]+)/;\n"); getResponse() .write("var pTableCellClass=/" + AlignmentTablePanel.tableCellClassPrefix + "([^\\s]+)/;\n"); getResponse().write("var alignment_columnheader_classname='" + AlignmentDisplayPanel.columnHeaderClassname + "';\n"); getResponse().write(String.format("var plotHeightDefault = %f,plotWidthDefault = %f;\n", AlignmentLinkedPlotPanel.plotImageHeight, AlignmentLinkedPlotPanel.plotImageWidth)); ////////////////////////////////////////////////// JavaScriptUtils.writeCloseTag(getResponse()); } } }