blob: d352860775db6bb849c33a9f8ca7689d26ff2de1 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.cocoon.generation.asciiart;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;
/**
* A drawing ascii art pad.
*
* @author huber@apache.org
* @since 18. Dezember 2002
* @version CVS $Id$
*/
public class AsciiArtPad {
private int width;
private int height;
/**
* List of AsciiArt elements
*/
private List pad;
private double xGrid;
private double yGrid;
/**
*Constructor for the AsciiArtPad object
*/
public AsciiArtPad() {
pad = new ArrayList();
}
/**
*Constructor for the AsciiArtPad object
*
*@param w Description of the Parameter
*@param h Description of the Parameter
*/
public AsciiArtPad(int w, int h) {
width = w;
height = h;
pad = new ArrayList();
}
/**
* Sets the width attribute of the AsciiArtPad object
*
*@param width The new width value
*/
public void setWidth(int width) {
this.width = width;
}
/**
* Sets the height attribute of the AsciiArtPad object
*
*@param height The new height value
*/
public void setHeight(int height) {
this.height = height;
}
/**
* Sets the xGrid attribute of the AsciiArtPad object
*
*@param xGrid The new xGrid value
*/
public void setXGrid(double xGrid) {
this.xGrid = xGrid;
}
/**
* Sets the yGrid attribute of the AsciiArtPad object
*
*@param yGrid The new yGrid value
*/
public void setYGrid(double yGrid) {
this.yGrid = yGrid;
}
/**
* Gets the width attribute of the AsciiArtPad object
*
*@return The width value
*/
public int getWidth() {
return width;
}
/**
* Gets the height attribute of the AsciiArtPad object
*
*@return The height value
*/
public int getHeight() {
return height;
}
/**
* Gets the xGrid attribute of the AsciiArtPad object
*
*@return The xGrid value
*/
public double getXGrid() {
return xGrid;
}
/**
* Gets the yGrid attribute of the AsciiArtPad object
*
*@return The yGrid value
*/
public double getYGrid() {
return yGrid;
}
/**
* Add a AsciiArtElement
*
*@param o the AsciiArtElement object
*/
public void add(Object o) {
pad.add(o);
}
/**
* Iterator of AsciiArtPad
*
*@return Iterator iterating over all AsciiArtElements
*/
public Iterator iterator() {
return pad.iterator();
}
/**
* An AsciiArtElement describing a line.
*
*/
public static class AsciiArtLine implements AsciiArtElement {
double xStart;
double yStart;
double xEnd;
double yEnd;
/**
*Constructor for the AsciiArtLine object
*
*@param start Description of the Parameter
*@param end Description of the Parameter
*/
public AsciiArtLine(AsciiArtCoordinate start, AsciiArtCoordinate end) {
xStart = start.getXDouble();
yStart = start.getYDouble();
xEnd = end.getXDouble();
yEnd = end.getYDouble();
}
/**
* Sets the xStart attribute of the AsciiArtLine object
*
*@param xStart The new xStart value
*/
public void setXStart(double xStart) {
this.xStart = xStart;
}
/**
* Sets the yStart attribute of the AsciiArtLine object
*
*@param yStart The new yStart value
*/
public void setYStart(double yStart) {
this.yStart = yStart;
}
/**
* Sets the xEnd attribute of the AsciiArtLine object
*
*@param xEnd The new xEnd value
*/
public void setXEnd(double xEnd) {
this.xEnd = xEnd;
}
/**
* Sets the yEnd attribute of the AsciiArtLine object
*
*@param yEnd The new yEnd value
*/
public void setYEnd(double yEnd) {
this.yEnd = yEnd;
}
/**
* Gets the xStart attribute of the AsciiArtLine object
*
*@return The xStart value
*/
public double getXStart() {
return xStart;
}
/**
* Gets the yStart attribute of the AsciiArtLine object
*
*@return The yStart value
*/
public double getYStart() {
return yStart;
}
/**
* Gets the xEnd attribute of the AsciiArtLine object
*
*@return The xEnd value
*/
public double getXEnd() {
return xEnd;
}
/**
* Gets the yEnd attribute of the AsciiArtLine object
*
*@return The yEnd value
*/
public double getYEnd() {
return yEnd;
}
/**
* Descriptive string
*
*@return String
*/
public String toString() {
String s =
"[xStart:" + String.valueOf(xStart) + "]" +
"[yStart:" + String.valueOf(yStart) + "]" +
"[xEnd:" + String.valueOf(xEnd) + "]" +
"[yEnd:" + String.valueOf(yEnd) + "]";
return s;
}
}
/**
* An AsciiArtElement describing a rectangle.
*
*/
public static class AsciiArtRect implements AsciiArtElement {
double xUpperLeft;
double yUpperLeft;
double xLowerRight;
double yLowerRight;
/**
*Constructor for the AsciiArtRect object
*
*@param upperLeft Description of the Parameter
*@param lowerRight Description of the Parameter
*/
public AsciiArtRect(AsciiArtCoordinate upperLeft, AsciiArtCoordinate lowerRight) {
xUpperLeft = upperLeft.getXDouble();
yUpperLeft = upperLeft.getYDouble();
xLowerRight = lowerRight.getXDouble();
yLowerRight = lowerRight.getYDouble();
}
/**
* Sets the xUpperLeft attribute of the AsciiArtRect object
*
*@param xUpperLeft The new xUpperLeft value
*/
public void setXUpperLeft(double xUpperLeft) {
this.xUpperLeft = xUpperLeft;
}
/**
* Sets the yUpperLeft attribute of the AsciiArtRect object
*
*@param yUpperLeft The new yUpperLeft value
*/
public void setYUpperLeft(double yUpperLeft) {
this.yUpperLeft = yUpperLeft;
}
/**
* Sets the xLowerRight attribute of the AsciiArtRect object
*
*@param xLowerRight The new xLowerRight value
*/
public void setXLowerRight(double xLowerRight) {
this.xLowerRight = xLowerRight;
}
/**
* Sets the yLowerRight attribute of the AsciiArtRect object
*
*@param yLowerRight The new yLowerRight value
*/
public void setYLowerRight(double yLowerRight) {
this.yLowerRight = yLowerRight;
}
/**
* Gets the xUpperLeft attribute of the AsciiArtRect object
*
*@return The xUpperLeft value
*/
public double getXUpperLeft() {
return xUpperLeft;
}
/**
* Gets the yUpperLeft attribute of the AsciiArtRect object
*
*@return The yUpperLeft value
*/
public double getYUpperLeft() {
return yUpperLeft;
}
/**
* Gets the xLowerRight attribute of the AsciiArtRect object
*
*@return The xLowerRight value
*/
public double getXLowerRight() {
return xLowerRight;
}
/**
* Gets the yLowerRight attribute of the AsciiArtRect object
*
*@return The yLowerRight value
*/
public double getYLowerRight() {
return yLowerRight;
}
/**
* Gets the width attribute of the AsciiArtRect object
*
*@return The width value
*/
public double getWidth() {
return Math.abs(xUpperLeft - xLowerRight);
}
/**
* Gets the height attribute of the AsciiArtRect object
*
*@return The height value
*/
public double getHeight() {
return Math.abs(yUpperLeft - yLowerRight);
}
/**
* Descriptive string
*
*@return String
*/
public String toString() {
String s =
"[xUpperLeft:" + String.valueOf(xUpperLeft) + "]" +
"[yUpperLeft:" + String.valueOf(yUpperLeft) + "]" +
"[xLowerRight:" + String.valueOf(xLowerRight) + "]" +
"[yLowerRight:" + String.valueOf(yLowerRight) + "]";
return s;
}
}
/**
* An AsciiArtElement describing a string of text.
*
*/
public static class AsciiArtString implements AsciiArtElement {
private double x;
private double y;
private String s;
/**
*Constructor for the AsciiArtString object
*
*@param s Description of the Parameter
*@param aac Description of the Parameter
*/
public AsciiArtString(AsciiArtCoordinate aac, String s) {
this.x = aac.getXDouble();
this.y = aac.getYDouble();
this.s = s;
}
/**
* Sets the x attribute of the AsciiArtString object
*
*@param x The new x value
*/
public void setX(double x) {
this.x = x;
}
/**
* Sets the y attribute of the AsciiArtString object
*
*@param y The new y value
*/
public void setY(double y) {
this.y = y;
}
/**
* Sets the s attribute of the AsciiArtString object
*
*@param s The new s value
*/
public void setS(String s) {
this.s = s;
}
/**
* Gets the x attribute of the AsciiArtString object
*
*@return The x value
*/
public double getX() {
return x;
}
/**
* Gets the y attribute of the AsciiArtString object
*
*@return The y value
*/
public double getY() {
return y;
}
/**
* Gets the s attribute of the AsciiArtString object
*
*@return The s value
*/
public String getS() {
return s;
}
/**
* Descriptive string
*
*@return String
*/
public String toString() {
String s =
"[x:" + String.valueOf(x) + "]" +
"[y:" + String.valueOf(y) + "]" +
"[s:" + String.valueOf(this.s) + "]";
return s;
}
}
/**
* Helper class describing a coordinate of AsciiArtPad elements.
*
*/
public static class AsciiArtCoordinate {
int x, y;
AsciiArtPad asciiArtPad;
double tx, ty;
/**
*Constructor for the AsciiArtCoordinate object
*/
public AsciiArtCoordinate() { }
/**
*Constructor for the AsciiArtCoordinate object
*
*@param asciiArtPad Description of the Parameter
*/
public AsciiArtCoordinate(AsciiArtPad asciiArtPad) {
setAsciiArtPad(asciiArtPad);
}
/**
*Constructor for the AsciiArtCoordinate object
*
*@param x Description of the Parameter
*@param y Description of the Parameter
*/
public AsciiArtCoordinate(int x, int y) {
setXY(x, y);
}
/**
* Sets the asciiArtPad attribute of the AsciiArtCoordinate object
*
*@param asciiArtPad The new asciiArtPad value
*/
public void setAsciiArtPad(AsciiArtPad asciiArtPad) {
this.asciiArtPad = asciiArtPad;
}
/**
* Sets the xY attribute of the AsciiArtCoordinate object
*
*@param tx The new transXY value
*@param ty The new transXY value
*/
public void setTransXY(double tx, double ty) {
this.tx = tx;
this.ty = ty;
}
/**
* Sets the xY attribute of the AsciiArtCoordinate object
*
*@param x The new xY value
*@param y The new xY value
*/
public void setXY(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Gets the xDouble attribute of the AsciiArtCoordinate object
*
*@return The xDouble value
*/
public double getXDouble() {
return x * asciiArtPad.getXGrid() + tx;
}
/**
* Gets the yDouble attribute of the AsciiArtCoordinate object
*
*@return The yDouble value
*/
public double getYDouble() {
return y * asciiArtPad.getYGrid() + ty;
}
}
/**
* Helper class containing the ascii text data,
* acting as input of an AsciiArtPad
*
*/
public static class AsciiArt {
private String[] s;
private int w;
private int h;
/**
*Constructor for the AsciiArt object
*
*@param s Description of the Parameter
*/
public AsciiArt(String[] s) {
this.s = s;
int length = s.length;
h = length;
w = 0;
for (int i = 0; i < length; i++) {
String line = s[i];
if (line != null && line.length() > w) {
w = line.length();
}
}
}
/**
* Gets the w attribute of the AsciiArt object
*
*@return The w value
*/
public int getW() {
return w;
}
/**
* Gets the h attribute of the AsciiArt object
*
*@return The h value
*/
public int getH() {
return h;
}
/**
* Gets the row attribute of the AsciiArt object
*
*@param r Description of the Parameter
*@return The row value
*/
public String getRow(int r) {
String row = this.s[r];
return row;
}
/**
* Gets the column attribute of the AsciiArt object
*
*@param c Description of the Parameter
*@return The column value
*/
public String getColumn(int c) {
StringBuffer column = new StringBuffer();
final String EMPTY_CHAR = " ";
for (int i = 0; i < s.length; i++) {
if (s[i] != null && c < s[i].length()) {
column.append(s[i].charAt(c));
} else {
column.append(EMPTY_CHAR);
}
}
return column.toString();
}
}
/**
* Builder of AsciiArtElements from an AsciiArt input.
*
*/
public static class AsciiArtPadBuilder {
private AsciiArtPad asciiArtPad;
private AsciiArt aa;
final static String EDGE_GROUP = "[+\\\\/]";
final static String HLINE_GROUP = "[\\-~=+]";
final static String VLINE_GROUP = "[|+]";
final static String STRING_SUFFIX_GROUP = "[^\\-|~=\\/+ \\\\]";
//final static String STRING_PREFIX_GROUP = "[a-zA-Z0-9_\\*;\\.#]";
final static String STRING_PREFIX_GROUP = STRING_SUFFIX_GROUP;
/**
*Constructor for the AsciiArtPadBuilder object
*
*@param asciiArtPad Description of the Parameter
*/
public AsciiArtPadBuilder(AsciiArtPad asciiArtPad) {
this.asciiArtPad = asciiArtPad;
}
/**
* Build AsciiArtElement from an asciiArt
*
*@param asciiArt Description of the Parameter
*/
public void build(String[] asciiArt) {
aa = new AsciiArt(asciiArt);
asciiArtPad.setWidth(aa.getW());
asciiArtPad.setHeight(aa.getH());
// find asciiArt patterns
findRectPattern();
findCornerPattern();
findLinePattern();
findStringPattern();
}
/**
* Find rectangles in the AsciiArt.
* not implemented yet.
*/
protected void findRectPattern() {
}
/**
* Find corners in the AsciiArt
*/
protected void findCornerPattern() {
AsciiArtCoordinate aacStart = new AsciiArtCoordinate(this.asciiArtPad);
aacStart.setTransXY(0, asciiArtPad.getYGrid() / 2);
AsciiArtCoordinate aacEnd = new AsciiArtCoordinate(this.asciiArtPad);
aacEnd.setTransXY(0, asciiArtPad.getYGrid() / 2);
// hor line
try {
final RE reCorner = new RE(EDGE_GROUP);
for (int r = 0; r < aa.getH(); r++) {
String row = aa.getRow(r);
int startIndex = 0;
while (reCorner.match(row, startIndex)) {
String s = reCorner.getParen(0);
int mStart = reCorner.getParenStart(0);
int mEnd = reCorner.getParenEnd(0);
if (s.equals("\\")) {
aacStart.setXY(mStart, r - 1);
aacEnd.setXY(mStart + 1, r);
} else if (s.equals("/")) {
aacStart.setXY(mStart + 1, r - 1);
aacEnd.setXY(mStart, r);
} else {
aacStart.setXY(mStart, r);
aacEnd.setXY(mStart, r);
}
AsciiArtLine aal = new AsciiArtLine(aacStart, aacEnd);
this.asciiArtPad.add(aal);
if (startIndex >= mEnd) {
break;
}
startIndex = mEnd;
}
}
} catch (RESyntaxException rese) {
rese.printStackTrace();
}
}
/**
* Find lines in the AsciiArt
*/
protected void findLinePattern() {
AsciiArtCoordinate aacStart = new AsciiArtCoordinate(this.asciiArtPad);
aacStart.setTransXY(0, asciiArtPad.getYGrid() / 2);
AsciiArtCoordinate aacEnd = new AsciiArtCoordinate(this.asciiArtPad);
aacEnd.setTransXY(0, asciiArtPad.getYGrid() / 2);
// hor line
try {
final RE reHorLine = new RE(HLINE_GROUP + "+");
for (int r = 0; r < aa.getH(); r++) {
String row = aa.getRow(r);
int startIndex = 0;
while (reHorLine.match(row, startIndex)) {
int mStart = reHorLine.getParenStart(0);
int mEnd = reHorLine.getParenEnd(0);
aacStart.setXY(mStart, r);
aacEnd.setXY(mEnd - 1, r);
AsciiArtLine aal = new AsciiArtLine(aacStart, aacEnd);
this.asciiArtPad.add(aal);
if (startIndex >= mEnd) {
break;
}
startIndex = mEnd;
}
}
} catch (RESyntaxException rese) {
rese.printStackTrace();
}
// ver line
try {
RE reVerLine = new RE(VLINE_GROUP + "+");
for (int c = 0; c < aa.getW(); c++) {
String col = aa.getColumn(c);
int startIndex = 0;
while (reVerLine.match(col, startIndex)) {
int mStart = reVerLine.getParenStart(0);
int mEnd = reVerLine.getParenEnd(0);
aacStart.setXY(c, mStart);
aacEnd.setXY(c, mEnd - 1);
AsciiArtLine aal = new AsciiArtLine(aacStart, aacEnd);
this.asciiArtPad.add(aal);
if (startIndex >= mEnd) {
break;
}
startIndex = mEnd;
}
}
} catch (RESyntaxException rese) {
rese.printStackTrace();
}
}
/**
* Find string text in the AsciiArt.
*/
protected void findStringPattern() {
AsciiArtCoordinate aacStart = new AsciiArtCoordinate(this.asciiArtPad);
aacStart.setTransXY(0, 3 * asciiArtPad.getYGrid() / 4);
// string
try {
final RE reString = new RE(STRING_PREFIX_GROUP + STRING_SUFFIX_GROUP + "*");
for (int r = 0; r < aa.getH(); r++) {
String row = aa.getRow(r);
int startIndex = 0;
while (reString.match(row, startIndex)) {
String s = reString.getParen(0);
int mStart = reString.getParenStart(0);
int mEnd = reString.getParenEnd(0);
aacStart.setXY(mStart, r);
AsciiArtString aas = new AsciiArtString(aacStart, s);
this.asciiArtPad.add(aas);
if (startIndex >= mEnd) {
break;
}
startIndex = mEnd;
}
}
} catch (RESyntaxException rese) {
rese.printStackTrace();
}
}
}
/**
* Marker interface of objects addable to the AsciiArtPad
*
*/
public static interface AsciiArtElement {
}
}