com.day.cq.wcm.foundation.ImageMap Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
/*
* Copyright 1997-2008 Day Management AG
* Barfuesserplatz 6, 4001 Basel, Switzerland
* All Rights Reserved.
*
* This software is the confidential and proprietary information of
* Day Management AG, ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Day.
*/
package com.day.cq.wcm.foundation;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class is used for parsing image map definitions as generated by the
* CqImageMap
component and make them available through an API to
* CQ components.
*
* The class is designed for single-threaded use.
*/
public class ImageMap {
/**
* Inner class that represents an area of the map.
*/
public class ImageArea {
/**
* type of the area (as required by the area tag)
*/
private final String type;
/**
* coordinates of the area (as required by the area tag)
*/
private final String coordinates;
/**
* HREF of the area (null
if none is specified)
*/
private final String href;
/**
* alternative text of the area (unicoded; null
if none is specified)
*/
private final String altText;
/**
* target of the area's HREF (null
if none is specified)
*/
private final String target;
/**
* Creates a new ImageArea
with the given parameters.
*
* @param type type/shape of the image area
* @param coordinates coordinates
* @param href HREF (optional)
* @param altText alternative text (optional)
* @param target target (frame/window; optional)
*/
protected ImageArea(String type, String coordinates, String href, String altText,
String target) {
log.debug("Creating image area; destination: {}; altText: {}; target: {}",
new Object[] { href, altText, target });
this.type = type;
this.coordinates = coordinates;
this.href = href;
this.altText = altText;
this.target = target;
}
/**
* Gets the type (= shape attribute) of the image area.
*
* @return type of the image area
*/
public String getType() {
return type;
}
/**
* Gets the coordinates (= coords attribute) of the image area.
*
* @return coordinates of the image area
*/
public String getCoordinates() {
return coordinates;
}
/**
* Gets the (optional) HREF of the image area.
*
* @return HREF of the image area; null
if undefined
*/
public String getHref() {
return href;
}
/**
* Gets the alternative text of the image area in unicode format.
*
* @return alternative text of the image area; null
if undefined
*/
public String getAltText() {
return altText;
}
/**
* Gets the target frame/window of the image area.
*
* @return target frame/window of the image area; null
if undefined
*/
public String getTarget() {
return target;
}
}
/**
* internal logger
*/
private static final Logger log = LoggerFactory.getLogger(ImageMap.class);
/**
* areas of the map
*/
private final List areas;
/**
* Creates a new ImageMap
object from the given string representation.
*
* @param mapDefinition string representation (as created by the
* CqImageMap
component)
* @return a suitable representation of the component
* @throws IllegalArgumentException if the given string representation is invalid
*/
public static ImageMap fromString(String mapDefinition)
throws IllegalArgumentException {
ImageMap theMap = new ImageMap();
theMap.createFromString(mapDefinition);
return theMap;
}
/**
* Private constructor.
*/
private ImageMap() {
this.areas = new ArrayList(10);
}
/**
* Decodes a string (encoded with encodeString()
that is contained in another
* string. The (partial) string to parse has to be enclosed in quotation marks.
*
* For example:
* decodeFromContainingString("x:\"abc\\"\"", 2)
will return
* { "decoded": "abc"", "nextPos": 9 }
*
* @param containingString the containing string
* @param parseStartPos position where parsing should start
* @return decoding result; Object[]
with the decoded string as first
* element (type String
); the first character position after the
* closing quotation as second element (type Integer
)
* @throws IllegalArgumentException if the string has an invalid format
*/
private Object[] decodeFromContainingString(String containingString,
int parseStartPos) {
int quotPos = containingString.indexOf("\"", parseStartPos);
if (quotPos < 0) {
throw new IllegalArgumentException(
"No opening quotation mark found in string.");
}
boolean isDone = false;
int currentCharPos = quotPos + 1;
StringBuilder text = new StringBuilder(128);
boolean isEscaped = false;
while (!isDone) {
char charToProcess = containingString.charAt(currentCharPos);
if ((charToProcess == '\"') && (!isEscaped)) {
isDone = true;
} else if (charToProcess == '\\') {
if (isEscaped) {
text.append("\\");
isEscaped = false;
} else {
isEscaped = true;
}
} else if (isEscaped) {
text.append(charToProcess);
isEscaped = false;
} else {
text.append(charToProcess);
}
currentCharPos++;
if ((currentCharPos >= containingString.length()) && (!isDone)) {
throw new IllegalArgumentException(
"No final quotation mark found in string.");
}
}
return new Object[] { text.toString(), currentCharPos };
}
/**
* Parses the destination from the given image map string (full version).
*
* @param value image map definition (full version)
* @param parseStartPos start position (in version
) where the destination
* has to be parsed from
* @return array with url as first element, target as second, text as third (all of them
* of type String
and the position of the next character to parse
* as fourth element (Integer
* @throws IllegalArgumentException if the string definition has a non-parseable format
*/
private Object[] parseAreaDestination(String value, int parseStartPos)
throws IllegalArgumentException {
int parsePos = parseStartPos;
Object[] parseResult;
char charToCheck;
String url = null;
if (parsePos < value.length()) {
charToCheck = value.charAt(parsePos);
if (charToCheck != '|') {
parseResult = this.decodeFromContainingString(value, parsePos);
url = (String) parseResult[0];
parsePos = (Integer) parseResult[1];
}
parsePos++;
}
String target = null;
if (parsePos < value.length()) {
charToCheck = value.charAt(parsePos);
if (charToCheck != '|') {
parseResult = this.decodeFromContainingString(value, parsePos);
target = (String) parseResult[0];
parsePos = (Integer) parseResult[1];
}
parsePos++;
}
String text = null;
if (parsePos < value.length()) {
charToCheck = value.charAt(parsePos);
if (charToCheck != ']') {
parseResult = this.decodeFromContainingString(value, parsePos);
if (parseResult == null) {
return null;
} else {
text = (String) parseResult[0];
parsePos = (Integer) parseResult[1];
}
}
}
return new Object[] { url, target, text, parsePos + 1 };
}
/**
* Creates a new ImageMap
object from the given string representation.
*
* @param strDefinition string representation (as created by the
* CqImageMap
component)
* @throws IllegalArgumentException if the given string representation is invalid
*/
private void createFromString(String strDefinition)
throws IllegalArgumentException {
this.areas.clear();
int processingPos = 0;
while (processingPos < strDefinition.length()) {
int startPos = strDefinition.indexOf("[", processingPos);
if (startPos < 0) {
break;
}
int coordEndPos = strDefinition.indexOf(")", startPos + 1);
if (coordEndPos < 0) {
break;
}
String areaDef = strDefinition.substring(startPos + 1, coordEndPos + 1);
int contentStartPos = areaDef.indexOf("(");
if (contentStartPos < 0) {
throw new IllegalArgumentException("Could not create image map; area "
+ "definition is not in format 'type(coords)...'.");
}
String type = areaDef.substring(0, contentStartPos);
String coords = areaDef.substring(contentStartPos + 1, areaDef.length() - 1);
Object[] areaDestination =
this.parseAreaDestination(strDefinition, coordEndPos + 1);
processingPos = (Integer) areaDestination[3];
String url = (String) areaDestination[0];
String target = (String) areaDestination[1];
String text = (String) areaDestination[2];
this.areas.add(new ImageArea(type, coords, url, text, target));
}
}
/**
* Returns the HTML code required for the image map.
*
* Parameters originalSize
and scaled
can be used to create
* a scaled map that is suitable for a scaled image.
*
* @param id id of the image map
* @return HTML code representing the image map
*/
public String draw(String id) {
StringBuilder htmlCode = new StringBuilder(128);
htmlCode.append("");
log.debug("Image map HTML code: {}", htmlCode);
return htmlCode.toString();
}
}