com.adobe.xfa.TextNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa;
import com.adobe.xfa.ut.ExFull;
/**
* A class to represent the textual content of an XFA element in the DOM.
*/
public class TextNode extends Chars {
private boolean mbIsFragment;
/**
* Instantiates a text node with the given text.
* @param parent the node's parent, if any.
* @param prevSibling the node's previous sibling, if any.
* @param text the node's text.
*/
public TextNode(Element parent, Node prevSibling, String text) {
super(parent, prevSibling, text);
setClass(STRS.TEXTNAME, XFA.TEXTNODETAG);
}
/**
* Instantiates a text node.
* @param parent the node's parent, if any.
* @param prevSibling the node's previous sibling, if any.
* @param text the char array that contains our text.
* @param start offset into the char array to start at.
* @param length the number of characters to take.
*
* @exclude from published api.
*/
public TextNode(Element parent, Node prevSibling, char[] text, int start, int length) {
super(parent, prevSibling, text, start, length);
setClass(STRS.TEXTNAME, XFA.TEXTNODETAG);
}
/**
* @exclude from published api.
*/
public Node clone(Element parent) {
return new TextNode(parent, null, getValue());
}
/**
* Creates a proto'ed TextNode. Modeled on Protoable.createProto().
* @exclude from published api.
*/
public TextNode createProto(Element oParent, String text, boolean bFull /* = false */) {
//
// Ensure the parent isn't null.
//
assert (oParent != null);
boolean bMute = false;
TextNode oRetNode = null;
try {
// Ensure createProto by default doesn't notify.
// If it does it will notify layout and cause it to be damaged.
// We only do this if bFull = false because bFull copies nodes without
// keeping the proto linkage
if (oParent != null && ! bFull) {
bMute = oParent.isMute();
oParent.mute();
}
Model oModel = oParent.getModel();
oRetNode = oModel.createTextNode(oParent, oParent.getLastXMLChild(), text);
if (oRetNode != null) {
if (isTransient() || oParent.isTransient() )
oRetNode.isTransient(true, true);
if (! bFull)
oRetNode.makeDefault();
else
oRetNode.makeNonDefault(false);
}
if (! bMute && oParent != null)
oParent.unMute();
}
catch(ExFull oEx) {
if (! bMute && oParent != null)
oParent.unMute();
throw oEx;
}
return oRetNode;
}
/**
* This is logically the equivalent of {@link Element#getDeltas(Element, XFAList)}, but
* it does not override it because TextNode does not derive from Element in XFA4J.
* @see Element#getDeltas(Element, XFAList)
* @exclude from public api.
*/
public void getDeltas(TextNode delta, XFAList list) {
// Adobe patent application tracking # B252, entitled METHOD AND SYSTEM TO PERSIST STATE, inventors: Roberto Perelman, Chris Solc, Anatole Matveief, Jeff Young, John Brinkman
// Adobe patent application tracking # B322, entitled METHOD AND SYSTEM TO MAINTAIN THE INTEGRITY OF A CERTIFIED DOCUMENT WHILE PERSISTING STATE IN A DYNAMIC FORM, inventors: Roberto Perelman, Chris Solc, Anatole Matveief, Jeff Young, John Brinkman
if (isSameClass(delta) && list != null) {
Element parent = getXFAParent();
Element deltaParent = delta.getXFAParent();
Delta newDelta = null;//CL#699561
if (delta.getModel().getAppModel() != null &&
!delta.getModel().getAppModel().getLegacySetting(AppModel.XFA_LEGACY_V32_SCRIPTING)) //bug 2603682
newDelta = new Delta(parent, deltaParent, this, delta, "value");
else
newDelta = new Delta(parent, deltaParent, this, delta, "");
list.append(newDelta);
}
}
/**
* @exclude from published api.
*/
public ScriptTable getScriptTable() {
return TextNodeScript.getScriptTable();
}
/**
* Gets this node's text value.
* @return the text value.
*/
public String getValue() {
return getText();
}
/**
* Gets this node's text value.
* @param value the text value.
*/
public void setValue(String value, boolean bNotify /* = true */, boolean bDefault /* = false */) {
setText(value);
// After a "set" operation we won't be a default property anymore, and
// we'll no longer delegate to any protos.
if (!bDefault)
makeNonDefault(false);
// Watson 1298960: if directly set, need to notify peers of
// change such that layout is aware of it.
if (bNotify)
notifyPeers(VALUE_CHANGED,"",null);
//setDirty(); // Chars.setText will have dirtied
}
/**
* Is this TextNode here as a result of a fragment relationship?
* @return fragment state
*
* @exclude from published api.
*/
public boolean isFragment() {
return mbIsFragment;
}
/**
* Set the fragment state of this node
* @param bFragment the fragment state
*
* @exclude from published api.
*/
public void isFragment(boolean bFragment) {
mbIsFragment = bFragment;
// if setting to false, set parent node to false
if (!bFragment) {
Element parent = getXMLParent();
if ((parent != null) && (parent.isFragment() == true))
parent.isFragment(false, false);
}
}
/**
* @see Node#makeNonDefault(boolean)
* @exclude from published api.
*/
public void makeNonDefault(boolean bRecursive /* = false */) {
super.makeNonDefault(bRecursive);
if (isFragment()) {
// If we're setting a property which is currently a result of an external
// proto (a.k.a. fragment) load, then we're effectively setting a local property
// override in the referencing doc and therefore need to clear the fragment flag
// from ancestors to allow saving of the override property.
isFragment(false);
// Since fragments can cause dom nodes to have both fragment and transient flags
// (loading with externalProtosAreTransient), clearing a 'fragment' flag (e.g. in order to
// override a fragment property while editing in Designer) then the transient flag also
// needs to clear or else the override property will be lost on save.
isTransient(false, false);
}
}
/**
* Restore a delta for this TextNode
* @param delta the delta to restore.
* @exclude
*/
void restoreDelta(TextNode delta) {
// Adobe patent application tracking # B252, entitled METHOD AND SYSTEM TO PERSIST STATE, inventors: Roberto Perelman, Chris Solc, Anatole Matveief, Jeff Young, John Brinkman
// Adobe patent application tracking # B322, entitled METHOD AND SYSTEM TO MAINTAIN THE INTEGRITY OF A CERTIFIED DOCUMENT WHILE PERSISTING STATE IN A DYNAMIC FORM, inventors: Roberto Perelman, Chris Solc, Anatole Matveief, Jeff Young, John Brinkman
Element parent = getXFAParent();
if (parent != null) {
// remove the delta from the parent
delta.remove();
// remove this node from the parent
remove();
// append the delta
parent.appendChild(delta, false);
delta.makeNonDefault(false);
}
}
/**
* Helper function for compareVersions.
*
* @exclude from published api.
*/
String trimTrailingZeros(String sSource) {
// Trim trailing 0's (and radix):
int nKeep = sSource.length();
boolean bRadixFound = false;
for (int i = 0; i < sSource.length(); i++) {
if (sSource.charAt(i) == '.') {
bRadixFound = true;
nKeep = i;
}
else if (bRadixFound && Character.isDigit(sSource.charAt(i)) && sSource.charAt(i) != '0') {
nKeep = i + 1;
}
}
return sSource.substring(0, nKeep);
}
/**
* Override of the corresponding Node.compareVersions.
*
* @exclude from published api.
*/
protected boolean compareVersions(Node oRollbackTextNode, Node oContainer, Node.ChangeLogger oChangeLogger, Object oUserData) {
boolean bMatches = compareVersionsBasic(oRollbackTextNode, oContainer, oChangeLogger, oUserData);
if (! bMatches)
return false;
//
// We're a leaf node. Compare PCDATA.
//
String sValue = ((TextNode) oRollbackTextNode).getValue();
//Bug#3047226: XTG does case insensitive comparison here. Need to do it explicitly in XFA4J.
if (! getValue().equalsIgnoreCase(sValue)) {
bMatches = false;
// Our number formatting is a bit buggy, and tends to end up with different canonical
// formats depending on whether the source was a merge or user input. If we did find
// a difference, we sanitize the strings to a single canonical format (no trailing zeros
// or radix) and try again. Watson 2301544.
Node oParent = getXFAParent();
if (oParent != null && (oParent.isSameClass(XFA.FLOATTAG) || oParent.isSameClass(XFA.DECIMALTAG))) {
String sSanitizedValue = trimTrailingZeros(getValue());
String sSanitizedRollback = trimTrailingZeros(sValue);
//Bug#3047226: XTG does case insensitive comparison here. Need to do it explicitly in XFA4J.
if (sSanitizedValue.equalsIgnoreCase(sSanitizedRollback))
bMatches = true;
}
if (bMatches == false && oChangeLogger != null)
logValueChangeHelper(oContainer, getValue(), oChangeLogger, oUserData);
}
return bMatches;
}
}