com.aoindustries.website.framework.TreePage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aoweb-framework Show documentation
Show all versions of aoweb-framework Show documentation
Legacy servlet-based web framework, superfast and capable but tedious to use.
/*
* aoweb-framework - Legacy servlet-based web framework, superfast and capable but tedious to use.
* Copyright (C) 2000-2013, 2014, 2015, 2016 AO Industries, Inc.
* [email protected]
* 7262 Bull Pen Cir
* Mobile, AL 36695
*
* This file is part of aoweb-framework.
*
* aoweb-framework is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* aoweb-framework is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with aoweb-framework. If not, see .
*/
package com.aoindustries.website.framework;
import com.aoindustries.encoding.ChainWriter;
import com.aoindustries.io.IoUtils;
import com.aoindustries.util.AoArrays;
import com.aoindustries.util.StringUtility;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
/**
* @author AO Industries, Inc.
*/
abstract public class TreePage extends WebPage {
private static final long serialVersionUID = 1L;
/**
* The color of the lines.
*/
public static final int TREE_LINE_COLOR=0xa8a8a8;
/**
* The parameter name to control the TreePage display mode.
*/
public static final String TREEPAGE_MODE="treepage_mode";
/**
* Indicates the TreePage should automatically select the correct mode,
* this is the default if the parameter is not provided.
*/
public static final String MODE_AUTO="auto";
/**
* Indicates the TreePage should display its contents in a text-only format.
*/
public static final String MODE_TEXT="text";
/**
* Indicates the TreePage should display its contents in an interactive format.
*/
public static final String MODE_GUI="gui";
/**
* The width of the images.
*/
private static final int IMAGE_WIDTH=24;
/**
* The height of the images.
*/
private static final int IMAGE_HEIGHT=32;
private static byte[] blank;
private static final byte[][] jpgCache=new byte[9][];
private static final byte[][] gifCache=new byte[9][];
private static byte[] getImageBytes(int imageNum, boolean isSmooth) throws IOException {
synchronized(jpgCache) {
byte[] bytes;
if(imageNum==0) {
// Load the blank image
bytes = blank;
if(bytes==null) {
try (InputStream in = TreePage.class.getResourceAsStream("images/blank.gif")) {
blank = bytes = IoUtils.readFully(in);
}
}
} else {
byte[][] cache=isSmooth?jpgCache:gifCache;
bytes=cache[imageNum-1];
if(bytes==null) {
try (InputStream in = TreePage.class.getResourceAsStream("images/tree_"+imageNum+"."+(isSmooth?"jpg":"gif"))) {
cache[imageNum-1] = bytes = IoUtils.readFully(in);
}
}
}
return bytes;
}
}
public TreePage(LoggerAccessor loggerAccessor) {
super(loggerAccessor);
}
public TreePage(WebSiteRequest req) {
super(req);
}
public TreePage(LoggerAccessor loggerAccessor, Object param) {
super(loggerAccessor, param);
}
@Override
public void doGet(WebSiteRequest req, HttpServletResponse resp) throws ServletException, IOException, SQLException {
String S=req.getParameter("image_num");
if(S==null) super.doGet(req, resp);
else {
try {
int imageNum=Integer.parseInt(S);
if(imageNum<0 || imageNum>9) {
req.setAttribute(TextOnlyLayout.HTTP_SERVLET_RESPONSE_STATUS, HttpServletResponse.SC_NOT_FOUND);
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Unable to find image number "+imageNum);
} else {
boolean useSmooth=useSmoothOutline(req);
resp.setContentType(imageNum==0?"image/gif":useSmooth?"image/jpeg":"image/gif");
byte[] bytes=getImageBytes(imageNum, useSmooth);
OutputStream out=resp.getOutputStream();
try {
out.write(bytes);
} finally {
out.flush();
out.close();
}
}
} catch(NumberFormatException err) {
req.setAttribute(TextOnlyLayout.HTTP_SERVLET_RESPONSE_STATUS, HttpServletResponse.SC_BAD_REQUEST);
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unable to parse image_num");
}
}
}
@Override
public long getSearchLastModified() throws IOException, SQLException {
return getClassLastModified();
}
@Override
public long getLastModified(WebSiteRequest req) {
if(req==null) return -1;
String S=req.getParameter("image_num");
return S==null?-1:getClassLoaderUptime();
}
@Override
public void doGet(
ChainWriter out,
WebSiteRequest req,
HttpServletResponse resp
) throws IOException, SQLException {
List extends TreePageData> tree = getTree(req);
String mode;
if(displayText(req)) {
int treeLen = tree.size();
// Break apart each line
String[][] paths = getLines(tree);
// Get the widest of the lines
int longest=0;
for(String path[] : paths) {
int width=0;
for (int d=0; d0) width+=3;
width+=path[d].length();
}
width+=3;
if(width>longest) longest=width;
}
out.print("\n");
String[] last = AoArrays.EMPTY_STRING_ARRAY;
for (int c = 0; c < treeLen; c++) {
int width = 0;
String[] path = paths[c];
int pathLen = path.length;
int max = Math.min(pathLen - 1, last.length);
int pos = 0;
for (; pos < max; pos++) {
if (last[pos].equals(path[pos])) {
if (pos > 0) {
boolean hasMore = false;
for (int d = c + 1; d < treeLen; d++) {
int end = pos;
for (int e = 0; e < end; e++) {
if (paths[d][e].equals(path[e])) {
if (e == (end - 1) && !paths[d][end].equals(path[end])) {
hasMore = true;
break;
}
} else break;
}
}
out.print(hasMore ? "| " : " ");
width += 3;
}
int len2 = last[pos].length();
for (int d = 0; d < len2; d++)
out.print(' ');
width += len2;
} else break;
}
for (; pos < pathLen; pos++) {
String replaced=replaceHTML(path[pos]);
if (pos>0 && replaced.length()>0) {
out.print("+--");
width += 3;
}
String href;
if (pos == (path[pathLen-1].length()==0?(pathLen-2):(pathLen-1)) && (href = tree.get(c).getUrl()) != null) {
out.print("").print(replaced).print("");
} else out.print(replaced);
String S;
if (replaced.length()>0 && (pos < (pathLen - 1) || ((S = tree.get(c).getPath()).length() > 0 && S.charAt(S.length() - 1) == '/')))
out.print('/');
else
out.print(' ');
width += replaced.length() + 1;
}
for (; width < longest; width++)
out.print(' ');
String description=tree.get(c).getDescription();
if(description!=null) out.println(description);
last = path;
}
out.print("
\n");
} else handleRequest(out, req, resp, tree, -1, -1, null);
}
@Override
protected void doPost(
WebSiteRequest req,
HttpServletResponse resp
) throws IOException, SQLException {
List extends TreePageData> tree = getTree(req);
// Get the scroll to position
int scrollToX = Integer.parseInt(req.getParameter("scroll_to_x"));
int scrollToY = Integer.parseInt(req.getParameter("scroll_to_y"));
ChainWriter out = getHTMLChainWriter(req, resp);
try {
WebPageLayout layout = getWebPageLayout(req);
layout.startHTML(
this,
req,
resp,
out,
scrollToX >= 0 ? ("window.scrollTo(" + scrollToX + ", " + scrollToY + ");") : null
);
int treeLen = tree.size();
boolean[] opened = new boolean[treeLen];
for (int c = 0; c < treeLen; c++) {
opened[c] = "true".equals(req.getParameter("opened_" + c));
}
// Print the new table
handleRequest(out, req, resp, tree, scrollToX, scrollToY, opened);
layout.endHTML(this, req, resp, out);
} finally {
out.flush();
out.close();
}
}
/**
* Gets the tree to be displayed. Each row consists of three elements: path, href, description
*/
abstract protected List extends TreePageData> getTree(WebSiteRequest req) throws IOException, SQLException;
/**
* Handles the interactive form of this page.
*/
private void handleRequest(
ChainWriter out,
WebSiteRequest req,
HttpServletResponse resp,
List extends TreePageData> tree,
int scrollToX,
int scrollToY,
boolean[] opened
) throws IOException, SQLException {
WebPageLayout layout=getWebPageLayout(req);
layout.startContent(out, req, resp, 1, getPreferredContentWidth(req));
layout.printContentTitle(out, req, resp, this, 1);
layout.printContentHorizontalDivider(out, req, resp, 1, false);
layout.startContentLine(out, req, resp, 1, null, null);
try {
// Get the tree data
int treeLen = tree.size();
// Break apart each line
String[][] paths = getLines(tree);
if (opened == null) {
// Default to opened for first item
opened = new boolean[treeLen];
if (treeLen > 0) opened[0] = true;
}
// Write the javascript that controls the form
out.print("\n");
// Write the form containing the current settings
out.print("\n");
} finally {
layout.endContentLine(out, req, resp, 1, false);
layout.endContent(this, out, req, resp, 1);
}
}
protected boolean useCodeFont(WebSiteRequest req) {
return false;
}
private static String[][] getLines(List extends TreePageData> tree) {
int treeLen = tree.size();
String[][] paths=new String[treeLen][];
for (int c = 0; c < treeLen; c++) {
List split = StringUtility.splitString(tree.get(c).getPath(), '/');
paths[c] = split.toArray(new String[split.size()]);
}
return paths;
}
private boolean displayText(WebSiteRequest req) throws IOException, SQLException {
// A search being performed
if(req==null) return true;
WebPageLayout layout=getWebPageLayout(req);
if(layout instanceof TextOnlyLayout) return true;
String mode=req.getParameter(TREEPAGE_MODE);
// Auto mode
if(mode==null || MODE_AUTO.equals(mode)) return req.isLynx();
// Text mode or default to gui mode
return MODE_TEXT.equals(mode);
}
abstract public boolean useSmoothOutline(WebSiteRequest req);
public static String replaceHTML(String S) {
return StringUtility.replace(S, "/", "/");
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy