js.template.xhtml.OperatorsList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of js-xhtml-template Show documentation
Show all versions of js-xhtml-template Show documentation
Reference implementation for j(s)-lib template API, declarative, natural and based on X(HT)ML language.
The newest version!
package js.template.xhtml;
import java.util.ArrayList;
import java.util.List;
import js.dom.Attr;
import js.dom.Element;
import js.lang.BugError;
import js.template.TemplateException;
/**
* Templates element operators list. Scan templates element attributes, looking for operators syntax and store {@link Meta
* meta-data} about operators found. There are semantic restrictions on element operators list, see below; this class takes care
* to enforce them and throws templates exception if semantic restriction is broken. Operators are grouped into types, see
* {@link Opcode.Type} and this class stores meta-data using the same structure.
*
* Operators list constrains
*
* - at most one conditional operator, see {@link Opcode.Type#CONDITIONAL} for a list of mutually excluding conditional
* operators,
*
- at most one content operator, see {@link Opcode.Type#CONTENT} for a list of mutually excluding content operators,
*
- at most one formatter instance declared; this constrain is actually enforced by XML syntax that does not allow for
* multiple attributes with the same name,
*
- format instance mandates {@link TextOperator} or {@link ValueOperator} presence.
*
*
* @author Iulian Rotaru
*/
final class OperatorsList {
/** Conditional operator meta-data. */
private Meta conditionalOperator;
/** Formatting instance meta-data. */
private Meta formattingOperator;
/** Content operator meta-data. */
private Meta contentOperator;
/** Attribute operators meta-data list. */
private List attributeOperators = new ArrayList();
/**
* Construct operators list instance. Scan element attributes looking for operators syntax and initialize internal
* meta-data.
*
* @param element element to scan for operators.
* @throws TemplateException if found operator with empty operand or if semantic restriction is broken.
*/
OperatorsList(Element element) {
for (Attr attr : element.getAttrs()) {
Opcode opcode = Opcode.fromAttrName(attr.getName());
if (opcode == Opcode.NONE) {
continue;
}
final String attrValue = attr.getValue();
if (attrValue.isEmpty()) {
throw new TemplateException("Empty operand on element |%s|.", element);
}
Meta meta = new Meta(opcode, attrValue);
switch (opcode.type()) {
case CONDITIONAL:
insanityCheck(element, this.conditionalOperator, opcode.type());
this.conditionalOperator = meta;
break;
case FORMATTING:
insanityCheck(element, this.formattingOperator, opcode.type());
this.formattingOperator = meta;
break;
case CONTENT:
insanityCheck(element, this.contentOperator, opcode.type());
this.contentOperator = meta;
break;
case ATTRIBUTE:
this.attributeOperators.add(meta);
break;
default:
throw new BugError("Invalid opcode type |%s|.", opcode.type());
}
}
}
/**
* Specialized constructor for elements that are items in a list or map.
*
* @param element element to scan for operators,
* @param isItem mark parameter for specialized constructor.
* @throws TemplateException if found operator with empty operand or if semantic restriction is broken.
*/
OperatorsList(Element element, boolean isItem) {
this(element);
if (contentOperator == null) {
Opcode opcode = element.hasChildren() ? js.template.xhtml.Opcode.OBJECT : js.template.xhtml.Opcode.TEXT;
contentOperator = new Meta(opcode, ".");
}
}
/**
* Throws template exception if operator of given type is already declared.
*
* @param element context element,
* @param meta operator meta-data,
* @param type operator type.
* @throws TemplateException if operator of given type is already declared.
*/
private void insanityCheck(Element element, Meta meta, Opcode.Type type) {
if (meta != null) {
throw new TemplateException("Invalid operators list on element |%s|. Only one %s operator is allowed.", element, type);
}
}
/**
* Return true if this operators list contains a conditional operator.
*
* @return true if conditional operator is present.
*/
boolean hasConditionalOperator() {
return conditionalOperator != null;
}
/**
* Get conditional operator meta-data.
*
* @return conditional operator meta-data.
*/
Meta getConditionalOperatorMeta() {
return conditionalOperator;
}
/**
* Return true if this operators list contains a formatting operator.
*
* @return true if formatting operator is present.
*/
boolean hasFormattingOperator() {
return formattingOperator != null;
}
/**
* Get formatting operator meta-data.
*
* @return formatting operator meta-data.
*/
Meta getFormattingOperatorMeta() {
return formattingOperator;
}
/**
* Return true if this operators list contains a content operator.
*
* @return true if content operators is present.
*/
boolean hasContentOperator() {
return contentOperator != null;
}
/**
* Get content operator meta-data.
*
* @return content operator meta-data.
*/
Meta getContentOperatorMeta() {
return contentOperator;
}
/**
* Get attribute operators meta-data list, possible empty.
*
* @return attribute operators meta-data.
*/
List getAttributeOperatorsMeta() {
return attributeOperators;
}
/**
* Operator meta-data extracted from template's element.
*
* @author Iulian Rotaru
*/
static final class Meta {
/** Operator opcode. */
Opcode opcode;
/** Operator operand. */
String operand;
/**
* Construct operator meta instance.
*
* @param opcode operator opcode,
* @param operand operator operand.
*/
private Meta(Opcode opcode, String operand) {
this.opcode = opcode;
this.operand = operand;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy