Package org.apache.xalan.templates
Class ElemTemplateElement
java.lang.Object
org.apache.xml.utils.UnImplNode
org.apache.xalan.templates.ElemTemplateElement
- All Implemented Interfaces:
Serializable
,SourceLocator
,XSLTVisitable
,PrefixResolver
,ExpressionNode
,WhitespaceStrippingElementMatcher
,Document
,Element
,Node
,NodeList
- Direct Known Subclasses:
DecimalFormatProperties
,ElemApplyImport
,ElemChoose
,ElemComment
,ElemCopyOf
,ElemEmpty
,ElemExtensionDecl
,ElemExtensionScript
,ElemFallback
,ElemForEach
,ElemIf
,ElemMessage
,ElemNumber
,ElemOtherwise
,ElemPI
,ElemSort
,ElemTemplate
,ElemText
,ElemTextLiteral
,ElemUse
,ElemValueOf
,ElemVariable
,ElemWhen
,ElemWithParam
,KeyDeclaration
,NamespaceAlias
,OutputProperties
,Stylesheet
,XSLTElementProcessor
public class ElemTemplateElement
extends UnImplNode
implements PrefixResolver, Serializable, ExpressionNode, WhitespaceStrippingElementMatcher, XSLTVisitable
An instance of this class represents an element inside
an xsl:template class. It has a single "execute" method
which is expected to perform the given action on the
result tree.
This class acts like a Element node, and implements the
Element interface, but is not a full implementation
of that interface... it only implements enough for
basic traversal of the tree.
- See Also:
-
Field Summary
Fields inherited from interface org.w3c.dom.Node
ATTRIBUTE_NODE, CDATA_SECTION_NODE, COMMENT_NODE, DOCUMENT_FRAGMENT_NODE, DOCUMENT_NODE, DOCUMENT_POSITION_CONTAINED_BY, DOCUMENT_POSITION_CONTAINS, DOCUMENT_POSITION_DISCONNECTED, DOCUMENT_POSITION_FOLLOWING, DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, DOCUMENT_POSITION_PRECEDING, DOCUMENT_TYPE_NODE, ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE, NOTATION_NODE, PROCESSING_INSTRUCTION_NODE, TEXT_NODE
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionAdd a child to the child list.appendChild
(Node newChild) Add a child to the child list.void
callVisitors
(XSLTVisitor visitor) This will traverse the heararchy, calling the visitor for each member.boolean
Tell if this element can accept variable declarations.boolean
Get information about whether or not whitespace can be stripped.int
Compares this object with the specified object for precedence order.void
compose
(StylesheetRoot sroot) This function is called after everything else has been recomposed, and allows the template to set remaining values that may be based on some other property that depends on recomposition.boolean
containsExcludeResultPrefix
(String prefix, String uri) Get whether or not the passed URL is contained flagged by the "extension-element-prefixes" property.void
endCompose
(StylesheetRoot sroot) This after the template's children have been composed.void
Throw an error.void
Throw a template element runtime error.void
execute
(TransformerImpl transformer) Execute the element's primary function.void
exprAddChild
(ExpressionNode n, int i) This method tells the node to add its argument to the node's list of children.exprGetChild
(int i) This method returns a child node.int
Return the number of children the node has.Get the ExpressionNode parent of this node.void
Set the parent of this node.Return the base identifier.Return the nodelist (same reference).int
Return the column number where the current document event ends.Return a table that contains all prefixes available within this element context.If this stylesheet was created from a DOM, get the DOM backpointer that this element originated from.int
Return the column number where the current document event ends.int
Return the line number where the current document event ends.Get the first child as a Node.Get the first child as a ElemTemplateElement.Get the last child.Get the last child.int
NodeList method: Count the immediate children of this nodeint
Return the line number where the current document event ends.For now, just return the result of getNodeName(), which the local name.getNamespaceForPrefix
(String prefix) Given a namespace, get the corrisponding prefix. 9/15/00: This had been iteratively examining the m_declaredPrefixes field for this node and its parents.getNamespaceForPrefix
(String prefix, Node context) Fullfill the PrefixResolver interface.Get the next sibling (as a Node) or return null.Get the next sibling (as a ElemTemplateElement) or return null.Return the node name.short
Get the type of the node.Get the stylesheet owner.Get the owning xsl:template element.Get the parent as an ElemTemplateElement.Get the parent as a Node.Get the parent element.Get the previous sibling (as a Node) or return null.Get the previous sibling (as a Node) or return null.Return the public identifier for the current document event.Get the owning stylesheet.Get the owning "composed" stylesheet.Get the owning root stylesheet.Return the system identifier for the current document event.Return the element name.int
getUid()
Get the UID (document order index).boolean
Get the "xml:space" attribute.int
Get an integer representation of the element type.boolean
boolean
Tell if there are child nodes.boolean
Tell if this element only has one text child, for optimization purposes.boolean
insertBefore
(Node newChild, Node refChild) Unimplemented.boolean
Tell if this template is a compiled template.item
(int index) NodeList method: Return the Nth immediate child of this node, or null if the index is out of bounds.void
recompose
(StylesheetRoot root) This function is called during recomposition to control how this element is composed.removeChild
(ElemTemplateElement childETE) Remove a child.replaceChild
(ElemTemplateElement newChildElem, ElemTemplateElement oldChildElem) Replace the old child with a new child.replaceChild
(Node newChild, Node oldChild) Replace the old child with a new child.void
Combine the parent's namespaces with this namespace for fast processing, taking care to reference the parent's namespace if this namespace adds nothing new.void
runtimeInit
(TransformerImpl transformer) This function will be called on top-level elements only, just before the transform begins.void
If this stylesheet was created from a DOM, set the DOM backpointer that this element originated from.void
setEndLocaterInfo
(SourceLocator locator) Set the end location information for this element.void
setLocaterInfo
(SourceLocator locator) Set the location information for this element.void
Set the parent as an ElemTemplateElement.void
setPrefixes
(NamespaceSupport nsSupport) From the SAX2 helper class, set the namespace table for this element.void
setPrefixes
(NamespaceSupport nsSupport, boolean excludeXSLDecl) Copy the namespace declarations from the NamespaceSupport object.void
setUid
(int i) Set the UID (document order index).void
setXmlSpace
(int v) Set the "xml:space" attribute.boolean
shouldStripWhiteSpace
(XPathContext support, Element targetElement) Get information about whether or not an element should strip whitespace.Methods inherited from class org.apache.xml.utils.UnImplNode
adoptNode, appendData, cloneNode, compareDocumentPosition, createAttribute, createAttributeNS, createCDATASection, createComment, createDocumentFragment, createElement, createElementNS, createEntityReference, createProcessingInstruction, createTextNode, deleteData, getActualEncoding, getAttribute, getAttributeNode, getAttributeNodeNS, getAttributeNS, getAttributes, getBaseURI, getDoctype, getDocumentElement, getDocumentURI, getDomConfig, getElementById, getElementsByTagName, getElementsByTagNameNS, getFeature, getImplementation, getInputEncoding, getNamespaceURI, getNodeValue, getOwnerElement, getPrefix, getSchemaTypeInfo, getSpecified, getStrictErrorChecking, getTextContent, getUserData, getWholeText, getXmlEncoding, getXmlStandalone, getXmlVersion, hasAttribute, hasAttributeNS, hasAttributes, importNode, insertData, isDefaultNamespace, isEqualNode, isId, isSameNode, isSupported, isWhitespaceInElementContent, lookupNamespaceURI, lookupPrefix, normalize, normalizeDocument, removeAttribute, removeAttributeNode, removeAttributeNS, removeChild, renameNode, replaceData, replaceWholeText, setActualEncoding, setAttribute, setAttributeNode, setAttributeNodeNS, setAttributeNS, setData, setDocumentURI, setIdAttribute, setIdAttribute, setIdAttributeNode, setIdAttributeNS, setInputEncoding, setNodeValue, setPrefix, setStrictErrorChecking, setTextContent, setUserData, setValue, setXmlEncoding, setXmlStandalone, setXmlVersion, splitText, substringData
-
Constructor Details
-
ElemTemplateElement
public ElemTemplateElement()Construct a template element instance.
-
-
Method Details
-
isCompiledTemplate
public boolean isCompiledTemplate()Tell if this template is a compiled template.- Returns:
- Boolean flag indicating whether this is a compiled template
-
getXSLToken
public int getXSLToken()Get an integer representation of the element type.- Returns:
- An integer representation of the element, defined in the Constants class.
- See Also:
-
getNodeName
Return the node name.- Specified by:
getNodeName
in interfaceNode
- Overrides:
getNodeName
in classUnImplNode
- Returns:
- An invalid node name
-
getLocalName
For now, just return the result of getNodeName(), which the local name.- Specified by:
getLocalName
in interfaceNode
- Overrides:
getLocalName
in classUnImplNode
- Returns:
- The result of getNodeName().
-
runtimeInit
This function will be called on top-level elements only, just before the transform begins.- Parameters:
transformer
- The XSLT TransformerFactory.- Throws:
TransformerException
-
execute
Execute the element's primary function. Subclasses of this function may recursivly execute down the element tree.- Parameters:
transformer
- The XSLT TransformerFactory.- Throws:
TransformerException
- if any checked exception occurs.
-
getStylesheetComposed
Get the owning "composed" stylesheet. This looks up the inheritance chain until it calls getStylesheetComposed on a Stylesheet object, which will Get the owning aggregated stylesheet, or that stylesheet if it is aggregated.- Returns:
- the owning "composed" stylesheet.
-
getStylesheet
Get the owning stylesheet. This looks up the inheritance chain until it calls getStylesheet on a Stylesheet object, which will return itself.- Returns:
- the owning stylesheet
-
getStylesheetRoot
Get the owning root stylesheet. This looks up the inheritance chain until it calls StylesheetRoot on a Stylesheet object, which will return a reference to the root stylesheet.- Returns:
- the owning root stylesheet
-
recompose
This function is called during recomposition to control how this element is composed.- Throws:
TransformerException
-
compose
This function is called after everything else has been recomposed, and allows the template to set remaining values that may be based on some other property that depends on recomposition.- Throws:
TransformerException
-
endCompose
This after the template's children have been composed.- Throws:
TransformerException
-
error
Throw a template element runtime error. (Note: should we throw a TransformerException instead?)- Overrides:
error
in classUnImplNode
- Parameters:
msg
- key of the error that occured.args
- Arguments to be used in the message
-
error
Description copied from class:UnImplNode
Throw an error.- Overrides:
error
in classUnImplNode
- Parameters:
msg
- Message Key for the error
-
appendChild
Add a child to the child list. NOTE: This presumes the child did not previously have a parent. Making that assumption makes this a less expensive operation -- but requires that if you *do* want to reparent a node, you use removeChild() first to remove it from its previous context. Failing to do so will damage the tree.- Specified by:
appendChild
in interfaceNode
- Overrides:
appendChild
in classUnImplNode
- Parameters:
newChild
- Child to be added to child list- Returns:
- Child just added to the child list
- Throws:
DOMException
-
appendChild
Add a child to the child list. NOTE: This presumes the child did not previously have a parent. Making that assumption makes this a less expensive operation -- but requires that if you *do* want to reparent a node, you use removeChild() first to remove it from its previous context. Failing to do so will damage the tree.- Parameters:
elem
- Child to be added to child list- Returns:
- Child just added to the child list
-
hasChildNodes
public boolean hasChildNodes()Tell if there are child nodes.- Specified by:
hasChildNodes
in interfaceNode
- Overrides:
hasChildNodes
in classUnImplNode
- Returns:
- True if there are child nodes
-
getNodeType
public short getNodeType()Get the type of the node.- Specified by:
getNodeType
in interfaceNode
- Overrides:
getNodeType
in classUnImplNode
- Returns:
- Constant for this node type
-
getChildNodes
Return the nodelist (same reference).- Specified by:
getChildNodes
in interfaceNode
- Overrides:
getChildNodes
in classUnImplNode
- Returns:
- The nodelist containing the child nodes (this)
-
removeChild
Remove a child. ADDED 9/8/200 to support compilation. TODO: ***** Alternative is "removeMe() from my parent if any" ... which is less well checked, but more convenient in some cases. Given that we assume only experts are calling this class, it might be preferable. It's less DOMish, though.- Parameters:
childETE
- The child to remove. This operation is a no-op if oldChild is not a child of this node.- Returns:
- the removed child, or null if the specified node was not a child of this element.
-
replaceChild
Replace the old child with a new child.- Specified by:
replaceChild
in interfaceNode
- Overrides:
replaceChild
in classUnImplNode
- Parameters:
newChild
- New child to replace witholdChild
- Old child to be replaced- Returns:
- The new child
- Throws:
DOMException
-
insertBefore
Unimplemented. See org.w3c.dom.Node- Specified by:
insertBefore
in interfaceNode
- Overrides:
insertBefore
in classUnImplNode
- Parameters:
newChild
- New child node to insertrefChild
- Insert in front of this child- Returns:
- null
- Throws:
DOMException
-
replaceChild
public ElemTemplateElement replaceChild(ElemTemplateElement newChildElem, ElemTemplateElement oldChildElem) Replace the old child with a new child.- Parameters:
newChildElem
- New child to replace witholdChildElem
- Old child to be replaced- Returns:
- The new child
- Throws:
DOMException
-
getLength
public int getLength()NodeList method: Count the immediate children of this node- Specified by:
getLength
in interfaceNodeList
- Overrides:
getLength
in classUnImplNode
- Returns:
- The count of children of this node
-
item
NodeList method: Return the Nth immediate child of this node, or null if the index is out of bounds.- Specified by:
item
in interfaceNodeList
- Overrides:
item
in classUnImplNode
- Parameters:
index
- Index of child to find- Returns:
- org.w3c.dom.Node: the child node at given index
-
getOwnerDocument
Get the stylesheet owner.- Specified by:
getOwnerDocument
in interfaceNode
- Overrides:
getOwnerDocument
in classUnImplNode
- Returns:
- The stylesheet owner
-
getOwnerXSLTemplate
Get the owning xsl:template element.- Returns:
- The owning xsl:template element, this element if it is a xsl:template, or null if not found.
-
getTagName
Return the element name.- Specified by:
getTagName
in interfaceElement
- Overrides:
getTagName
in classUnImplNode
- Returns:
- The element name
-
hasTextLitOnly
public boolean hasTextLitOnly()Tell if this element only has one text child, for optimization purposes.- Returns:
- true of this element only has one text literal child.
-
getBaseIdentifier
Return the base identifier.- Specified by:
getBaseIdentifier
in interfacePrefixResolver
- Returns:
- The base identifier
-
getEndLineNumber
public int getEndLineNumber()Return the line number where the current document event ends. Note that this is the line position of the first character after the text associated with the document event.- Returns:
- The line number, or -1 if none is available.
- See Also:
-
getLineNumber
public int getLineNumber()Return the line number where the current document event ends. Note that this is the line position of the first character after the text associated with the document event.- Specified by:
getLineNumber
in interfaceSourceLocator
- Returns:
- The line number, or -1 if none is available.
- See Also:
-
getEndColumnNumber
public int getEndColumnNumber()Return the column number where the current document event ends. Note that this is the column number of the first character after the text associated with the document event. The first column in a line is position 1.- Returns:
- The column number, or -1 if none is available.
- See Also:
-
getColumnNumber
public int getColumnNumber()Return the column number where the current document event ends. Note that this is the column number of the first character after the text associated with the document event. The first column in a line is position 1.- Specified by:
getColumnNumber
in interfaceSourceLocator
- Returns:
- The column number, or -1 if none is available.
- See Also:
-
getPublicId
Return the public identifier for the current document event.This will be the public identifier
- Specified by:
getPublicId
in interfaceSourceLocator
- Returns:
- A string containing the public identifier, or null if none is available.
- See Also:
-
getSystemId
Return the system identifier for the current document event.If the system identifier is a URL, the parser must resolve it fully before passing it to the application.
- Specified by:
getSystemId
in interfaceSourceLocator
- Returns:
- A string containing the system identifier, or null if none is available.
- See Also:
-
setLocaterInfo
Set the location information for this element.- Parameters:
locator
- Source Locator with location information for this element
-
setEndLocaterInfo
Set the end location information for this element.- Parameters:
locator
- Source Locator with location information for this element
-
hasVariableDecl
public boolean hasVariableDecl() -
setXmlSpace
public void setXmlSpace(int v) Set the "xml:space" attribute. A text node is preserved if an ancestor element of the text node has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.- Parameters:
v
- Enumerated value, either Constants.ATTRVAL_PRESERVE or Constants.ATTRVAL_STRIP.- See Also:
-
getXmlSpace
public boolean getXmlSpace()Get the "xml:space" attribute. A text node is preserved if an ancestor element of the text node has an xml:space attribute with a value of preserve, and no closer ancestor element has xml:space with a value of default.- Returns:
- The value of the xml:space attribute
- See Also:
-
getDeclaredPrefixes
Return a table that contains all prefixes available within this element context.- Returns:
- Vector containing the prefixes available within this element context
-
setPrefixes
From the SAX2 helper class, set the namespace table for this element. Take care to call resolveInheritedNamespaceDecls. after all namespace declarations have been added.- Parameters:
nsSupport
- non-null reference to NamespaceSupport from the ContentHandler.- Throws:
TransformerException
-
setPrefixes
public void setPrefixes(NamespaceSupport nsSupport, boolean excludeXSLDecl) throws TransformerException Copy the namespace declarations from the NamespaceSupport object. Take care to call resolveInheritedNamespaceDecls. after all namespace declarations have been added.- Parameters:
nsSupport
- non-null reference to NamespaceSupport from the ContentHandler.excludeXSLDecl
- true if XSLT namespaces should be ignored.- Throws:
TransformerException
-
getNamespaceForPrefix
Fullfill the PrefixResolver interface. Calling this for this class will throw an error.- Specified by:
getNamespaceForPrefix
in interfacePrefixResolver
- Parameters:
prefix
- The prefix to look up, which may be an empty string ("") for the default Namespace.context
- The node context from which to look up the URI.- Returns:
- null if the error listener does not choose to throw an exception.
-
getNamespaceForPrefix
Given a namespace, get the corrisponding prefix. 9/15/00: This had been iteratively examining the m_declaredPrefixes field for this node and its parents. That makes life difficult for the compilation experiment, which doesn't have a static vector of local declarations. Replaced a recursive solution, which permits easier subclassing/overriding.- Specified by:
getNamespaceForPrefix
in interfacePrefixResolver
- Parameters:
prefix
- non-null reference to prefix string, which should map to a namespace URL.- Returns:
- The namespace URL that the prefix maps to, or null if no mapping can be found.
-
containsExcludeResultPrefix
Get whether or not the passed URL is contained flagged by the "extension-element-prefixes" property. This method is overridden byElemLiteralResult.containsExcludeResultPrefix(java.lang.String, java.lang.String)
.- Parameters:
prefix
- non-null reference to prefix that might be excluded.- Returns:
- true if the prefix should normally be excluded.
- See Also:
-
resolvePrefixTables
Combine the parent's namespaces with this namespace for fast processing, taking care to reference the parent's namespace if this namespace adds nothing new. (Recursive method, walking the elements depth-first, processing parents before children). Note that this method builds m_prefixTable with aliased namespaces, *not* the original namespaces.- Throws:
TransformerException
-
setUid
public void setUid(int i) Set the UID (document order index).- Parameters:
i
- Index of this child.
-
getUid
public int getUid()Get the UID (document order index).- Returns:
- Index of this child
-
getParentNode
Get the parent as a Node.- Specified by:
getParentNode
in interfaceNode
- Overrides:
getParentNode
in classUnImplNode
- Returns:
- This node's parent node
-
getParentElem
Get the parent as an ElemTemplateElement.- Returns:
- This node's parent as an ElemTemplateElement
-
setParentElem
Set the parent as an ElemTemplateElement.- Parameters:
p
- This node's parent as an ElemTemplateElement
-
getNextSibling
Get the next sibling (as a Node) or return null.- Specified by:
getNextSibling
in interfaceNode
- Overrides:
getNextSibling
in classUnImplNode
- Returns:
- this node's next sibling or null
-
getPreviousSibling
Get the previous sibling (as a Node) or return null. Note that this may be expensive if the parent has many kids; we accept that price in exchange for avoiding the prev pointer TODO: If we were sure parents and sibs are always ElemTemplateElements, we could hit the fields directly rather than thru accessors.- Specified by:
getPreviousSibling
in interfaceNode
- Overrides:
getPreviousSibling
in classUnImplNode
- Returns:
- This node's previous sibling or null
-
getPreviousSiblingElem
Get the previous sibling (as a Node) or return null. Note that this may be expensive if the parent has many kids; we accept that price in exchange for avoiding the prev pointer TODO: If we were sure parents and sibs are always ElemTemplateElements, we could hit the fields directly rather than thru accessors.- Returns:
- This node's previous sibling or null
-
getNextSiblingElem
Get the next sibling (as a ElemTemplateElement) or return null.- Returns:
- This node's next sibling (as a ElemTemplateElement) or null
-
getParentNodeElem
Get the parent element.- Returns:
- This node's next parent (as a ElemTemplateElement) or null
-
getFirstChild
Get the first child as a Node.- Specified by:
getFirstChild
in interfaceNode
- Overrides:
getFirstChild
in classUnImplNode
- Returns:
- This node's first child or null
-
getFirstChildElem
Get the first child as a ElemTemplateElement.- Returns:
- This node's first child (as a ElemTemplateElement) or null
-
getLastChild
Get the last child.- Specified by:
getLastChild
in interfaceNode
- Overrides:
getLastChild
in classUnImplNode
- Returns:
- This node's last child
-
getLastChildElem
Get the last child.- Returns:
- This node's last child
-
getDOMBackPointer
If this stylesheet was created from a DOM, get the DOM backpointer that this element originated from. For tooling use.- Returns:
- DOM backpointer that this element originated from or null.
-
setDOMBackPointer
If this stylesheet was created from a DOM, set the DOM backpointer that this element originated from. For tooling use.- Parameters:
n
- DOM backpointer that this element originated from.
-
compareTo
Compares this object with the specified object for precedence order. The order is determined by the getImportCountComposed() of the containing composed stylesheet and the getUid() of this element. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.- Parameters:
o
- The object to be compared to this object- Returns:
- a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
- Throws:
ClassCastException
- if the specified object's type prevents it from being compared to this Object.
-
shouldStripWhiteSpace
public boolean shouldStripWhiteSpace(XPathContext support, Element targetElement) throws TransformerException Get information about whether or not an element should strip whitespace.- Specified by:
shouldStripWhiteSpace
in interfaceWhitespaceStrippingElementMatcher
- Parameters:
support
- The XPath runtime state.targetElement
- Element to check- Returns:
- true if the whitespace should be stripped.
- Throws:
TransformerException
- See Also:
-
canStripWhiteSpace
public boolean canStripWhiteSpace()Get information about whether or not whitespace can be stripped.- Specified by:
canStripWhiteSpace
in interfaceWhitespaceStrippingElementMatcher
- Returns:
- true if the whitespace can be stripped.
- See Also:
-
canAcceptVariables
public boolean canAcceptVariables()Tell if this element can accept variable declarations.- Returns:
- true if the element can accept and process variable declarations.
-
exprSetParent
Set the parent of this node.- Specified by:
exprSetParent
in interfaceExpressionNode
- Parameters:
n
- Must be a ElemTemplateElement.
-
exprGetParent
Get the ExpressionNode parent of this node.- Specified by:
exprGetParent
in interfaceExpressionNode
-
exprAddChild
This method tells the node to add its argument to the node's list of children.- Specified by:
exprAddChild
in interfaceExpressionNode
- Parameters:
n
- Must be a ElemTemplateElement.
-
exprGetChild
This method returns a child node. The children are numbered from zero, left to right.- Specified by:
exprGetChild
in interfaceExpressionNode
-
exprGetNumChildren
public int exprGetNumChildren()Return the number of children the node has.- Specified by:
exprGetNumChildren
in interfaceExpressionNode
-
callVisitors
Description copied from interface:XSLTVisitable
This will traverse the heararchy, calling the visitor for each member. If the called visitor method returns false, the subtree should not be called.- Specified by:
callVisitors
in interfaceXSLTVisitable
- Parameters:
visitor
- The visitor whose appropriate method will be called.- See Also:
-
handlesNullPrefixes
public boolean handlesNullPrefixes()- Specified by:
handlesNullPrefixes
in interfacePrefixResolver
- See Also:
-