com.adobe.xfa.AppModel Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
/*
* 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.xml.sax.Attributes;
import com.adobe.xfa.form.FormModel;
import com.adobe.xfa.service.storage.PacketHandler;
import com.adobe.xfa.template.TemplateModel;
import com.adobe.xfa.ut.ExFull;
import com.adobe.xfa.ut.FindBugsSuppress;
import com.adobe.xfa.ut.MsgFormat;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.StringUtils;
/**
* A class to represent the top level element in the XFA object model.
* All application-specific models are represented as sub-models
* of this one.
*Example:
* xfa <- this is the AppModel
* datasets <- this is the XFADataModel
* data <- this is $data in SOM expressions (a datagroup)
*/
public final class AppModel extends Model implements Model.DualDomModel {
public static class LegacyMask {
private static final int LegacyMask_BitSize = 2;
private int[] nBits;
public LegacyMask(int nBitsIdx) {
this(nBitsIdx, 0);
}
public LegacyMask(int nBitsIdx, int nIndex) {
assert(nIndex=LegacyMask_BitSize) {
//jfString errorStr("Error");
//jfFormat errorFmt(errorStr);
//throw jfExFull();
return;
}
nBits[nIndex] |= nBitsIdx;
}
public LegacyMask(LegacyMask inLegacyMask) {
nBits = new int[LegacyMask_BitSize];
for (int i=0; i= 2.8)
// Note: v2.7-multiRecordContextCache is off by default for all versions of xfa
//
// Positioning Render Event PlusPrint CalcOverride Permissions V26HiddenPositioned V27MultiRecordContextCache V27Layout V27Scripting V27EventModel V27TraversalOrder
// 2.8
// 2.7 x x x x x
// 2.6 x x x x x x
// 2.5 x x x x x x
// 2.4 x x x x x x x x x
// 2.3 x x x x x x x x x x
// 2.2 x x x x x x x x x x
// 2.1 x x x x x x x x x x x x
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_35_DEFAULT = new LegacyMask(0);
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_HEAD_DEFAULT = new LegacyMask(XFA_LEGACY_35_DEFAULT);
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_34_DEFAULT = new LegacyMask(XFA_LEGACY_35_DEFAULT);
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_33_DEFAULT = new LegacyMask(XFA_LEGACY_34_DEFAULT);
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_32_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_33_DEFAULT, XFA_LEGACY_V32_SCRIPTING, XFA_LEGACY_V32_LAYOUT, XFA_LEGACY_V32_RENDERING, XFA_LEGACY_V32_CANONICALIZATION});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_31_DEFAULT = new LegacyMask(XFA_LEGACY_32_DEFAULT);
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_30_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_31_DEFAULT, XFA_LEGACY_V30_LAYOUT, XFA_LEGACY_V30_SCRIPTING});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_29_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_30_DEFAULT, XFA_LEGACY_V29_LAYOUT, XFA_LEGACY_V29_SCRIPTING, XFA_LEGACY_V29_TRAVERSALORDER, XFA_LEGACY_V29_FIELDPRESENCE});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_28_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_29_DEFAULT, XFA_LEGACY_V28_LAYOUT, XFA_LEGACY_V28_SCRIPTING});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_27_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_28_DEFAULT, XFA_LEGACY_V27_LAYOUT, XFA_LEGACY_V27_SCRIPTING, XFA_LEGACY_V27_EVENTMODEL, XFA_LEGACY_V27_TRAVERSALORDER, XFA_LEGACY_V27_XHTMLVERSIONPROCESSING});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_26_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_27_DEFAULT, XFA_LEGACY_V26_HIDDENPOSITIONED});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_25_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_26_DEFAULT});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_24_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_25_DEFAULT, XFA_LEGACY_PLUSPRINT, XFA_LEGACY_CALCOVERRIDE, XFA_LEGACY_PERMISSIONS});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_23_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_24_DEFAULT, XFA_LEGACY_EVENTMODEL});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_22_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_23_DEFAULT});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_21_DEFAULT = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_22_DEFAULT, XFA_LEGACY_POSITIONING});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_21_DEPRECATED = new LegacyMask(0);
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_22_DEPRECATED = XFA_LEGACY_21_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_23_DEPRECATED = XFA_LEGACY_22_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_24_DEPRECATED = XFA_LEGACY_23_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_25_DEPRECATED = XFA_LEGACY_24_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_26_DEPRECATED = XFA_LEGACY_25_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_27_DEPRECATED = XFA_LEGACY_26_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_28_DEPRECATED = XFA_LEGACY_27_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_29_DEPRECATED = XFA_LEGACY_28_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_30_DEPRECATED = XFA_LEGACY_29_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_31_DEPRECATED = XFA_LEGACY_30_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_32_DEPRECATED = XFA_LEGACY_31_DEPRECATED;
// XFA Legacy settings deprecated by version.
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_33_DEPRECATED = LegacyMask.or(new LegacyMask[]{XFA_LEGACY_32_DEPRECATED, XFA_LEGACY_RENDERING, XFA_LEGACY_POSITIONING});
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_34_DEPRECATED = XFA_LEGACY_33_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_35_DEPRECATED = XFA_LEGACY_34_DEPRECATED;
/**
* @exclude from published api.
*/
public final static LegacyMask XFA_LEGACY_HEAD_DEPRECATED = XFA_LEGACY_35_DEPRECATED;
private static final AppSchema gAppSchema = new AppSchema();
static Schema getModelSchema() {
return gAppSchema;
}
/**
* Determines if a packet should be included based on a packet list.
* @param aPacketName the packet to test for
* @param sInList the list of packets
* @return boolean -- in or out.
*/
public static boolean includePacket(String aPacketName, String sInList) {
String sPackets = sInList;
if (StringUtils.isEmpty(sInList))
return false;
boolean bInclude = true;
// exclusive list
if (sPackets.startsWith("-")) {
sPackets = sPackets.substring(1);
bInclude = false;
}
if (sPackets.indexOf('*') != -1)
return bInclude;
String sPacketName = aPacketName;
String sTokens[] = sPackets.split(" ");
for (int i = 0; i < sTokens.length; i++) {
if (sTokens[i].equals(sPacketName)) {
return bInclude;
}
}
return !bInclude;
}
private boolean mbExternalProtosAreTransient;
private boolean mbIsFragmentDoc;
private boolean mbResolveAllExternalProtos = true; // cs TODO for now default to true until merge can do this
private boolean mbUpdateOriginalVersion = true; // for designer only
private DependencyTracker mDependencyTracker;
private int meOutputBelow = EnumAttr.OUTPUTBELOW_WARN;
private int meSourceAbove = EnumAttr.SOURCEABOVE_WARN;
private int meSourceBelow = EnumAttr.SOURCEBELOW_UPDATE;
private EventManager mEventManager;
/**
* Concatenated list of errors of all child models.
*/
//private ArrayList mExtendedErrorList;
/**
* Support for pseudo models
*/
private final Map mExtraShortCuts = new HashMap();
private final List mFactories = new ArrayList();
private final List mScriptHandlers = new ArrayList();
private HrefHandler mHrefHandler;
private PacketHandler mPacketHandler;
private Object mHandlerData;
private LogMessenger mMessenger; // For log messages
private int mnMaxVersionAllowed = Schema.XFAVERSION_HEAD;
// By default, the XFA verison is not bumped when loading rich text. Designer needs to be able
// to enable bumping for loading rich text.
private boolean mbBumpVersionOnRichTextLoad;
/**
* moFragmentSearchPath records a list of places to look for external documents (i.e. hrefs).
* It's only populated within fragments.
*/
private List moFragmentSearchPath;
private String msPackets = "";
private boolean mbAllowThirdPartyXml;
/**
* Instantiates an app model with the given messenger.
* @param messenger a log messenger, if any.
*/
public AppModel(LogMessenger messenger /*= XFALogMessenger() */) {
super(null, null, "", XFA.XFA, XFA.XFA, STRS.DOLLARXFA, XFA.XFATAG, XFA.XFA, getModelSchema());
setName(XFA.XFA);
if (messenger == null)
messenger = new LogMessenger();
mMessenger = messenger;
mEventManager = new EventManager(this);
// The Document constructor calls AppModel.setDocument()
/* mDocument = */new Document(this);
setAppModel(this);
// An AppModel starts out with an orphaned XML peer.
ModelPeer xmlPeer = new ModelPeer(null, null, "", XFA.XFA, XFA.XFA, null, this);
xmlPeer.setModel(this);
setXmlPeer(xmlPeer);
addPseudoModel(STRS.DOLLARLOG, new LogPseudoModel(this));
addPseudoModel(STRS.DOLLAREVENT, new EventPseudoModel(this));
}
/**
* Adds a model factory to the list of registered factories.
*
* Factories are added for models that are to be loaded with a full
* implementation.
* If no model is explicitly added, a default model with minimal
* functionality will be used.
* @param factory the factory to add.
*/
@FindBugsSuppress(code="ES")
public void addFactory(ModelFactory factory) {
int count = mFactories.size();
//
// Replace an earlier version of this factory if it exists.
//
for (int i = 0; i < count; i++) {
if (factory.rootName() == mFactories.get(i).rootName()) {
mFactories.remove(i);
break;
}
}
mFactories.add(factory);
}
/**
* Makes an object visible to the global scripting namespace.
* The obj
parameter will typically be derived
* from PseudoModel
.
* The shortcut name must start with a dollar sign ($).
*
* For example, an application might use this method to
* add an object derived from HostPseudoModel
and
* register it with the name $host
.
* @param sShortCutName the name of the scripting object.
* @param obj the scriptable object
* @see #removePseudoModel(String)
*/
public void addPseudoModel(String sShortCutName, Obj obj) {
assert sShortCutName.startsWith("$");
// ensure that sShortCutName is not already added
assert mExtraShortCuts.get(sShortCutName) == null;
assert obj != null;
mExtraShortCuts.put(sShortCutName, obj);
}
/**
* Adds (registers) a script handler for this app model.
*
* Script handlers are added to provide scripting support for various
* languages.
*
* @param handler the script handler to add.
*/
public void addScriptHandler(ScriptHandler handler){
for (int i = 0; i < mScriptHandlers.size(); i++) {
ScriptHandler oHandler = mScriptHandlers.get(i);
if (oHandler.languageName().equals(handler.languageName())) {
mScriptHandlers.remove(i);
i--;
}
}
mScriptHandlers.add(handler.clone());
}
/**
* Clears any scripting contexts associated with all script
* handlers previously registered with this app model.
* @see #addScriptHandler(ScriptHandler)
*/
public void clearScriptingContexts() {
for (int i = 0; i < mScriptHandlers.size(); i++) {
mScriptHandlers.get(i).clearExecutionContexts();
}
// JavaPort: extended from the C++ to purge cleared
// script handlers from the list, ensuring that repeated
// clearings won't do anything.
while(mScriptHandlers.size()>0) mScriptHandlers.remove(0);
}
/**
* Gets a boolean which indicates whether the XFA version should be bumped when loading rich text
* containing features not supported by the form's current version. This is false
by default.
* Only Designer is expected to make use of this flag.
* @return true
if version bumping is enabled for rich text loading.
* @exclude from published api.
*/
public boolean bumpVersionOnRichTextLoad() {
return mbBumpVersionOnRichTextLoad;
}
/**
* Sets a boolean which indicates whether the XFA version should be bumped when loading rich text
* containing features not supported by the form's current version. This is false
by default.
* Only Designer is expected to make use of this flag
* @param bBumpVersion true
to enable version bumping when loading rich text.
* @exclude from published api.
*/
public void bumpVersionOnRichTextLoad(boolean bBumpVersion) {
mbBumpVersionOnRichTextLoad = bBumpVersion;
}
/**
* @see Element#appendChild(Node, boolean)
*/
public void appendChild(Node newChild, boolean bValidate) {
//Overwritten to facilitate the adding of other models to an app model
assert(newChild != null);
if (newChild instanceof Model) {
Model newModel = (Model)newChild;
//Append it on the xfa side only. Since we know it's a model we don't need to call updateModel or import dom docs
super.appendChild(newModel, bValidate);
newModel.setAppModel(this);
}
else
super.appendChild(newChild, bValidate);
}
/**
* Clears this app model's current list of errors.
* @see Model#clearErrorList()
*/
public void clearErrorList() {
// Clear any errors in this XFAAppModelImpl
super.clearErrorList();
// Clear errors of child models
Node child = getFirstXFAChild();
while (child != null) {
if (child instanceof Model)
((Model)child).clearErrorList();
child = child.getNextXFASibling();
}
}
/**
* @see Model#createNode(int, Element, String, String, boolean)
*
* @exclude from published api.
*/
public Node createNode(int eTag, Element parent, String aName, String aNS, boolean bDoVersionCheck) {
assert (aName != null);
assert (aNS != null);
if (eTag == XFA.PACKETTAG) {
Packet packet = new Packet(this, null);
ModelPeer modelPeer = new ModelPeer((Element)getXmlPeer(), null, aNS, aName, aName, null, packet);
packet.setXmlPeer(modelPeer);
return packet;
}
// this is overridden just to prevent a software failure in XFAModelImpl
throw new ExFull(new MsgFormat(ResId.InvalidNodeTypeException, getAtom(eTag)));
}
/**
* @see Model#createElement(Element, Node, String, String, String, Attributes, int, String)
*
* @exclude from published api.
*/
@FindBugsSuppress(code="ES")
public Element createElement(Element parent, Node prevSibling, String uri, String localName, String qName, Attributes attributes, int lineNumber, String fileName) {
super.setLineNumber(lineNumber);
if (parent == this || parent instanceof Document) {
//
// Filter out packets if specified.
//
String sPackets = getPacketList();
if (sPackets.length() > 0) {
StringTokenizer sFilter = new StringTokenizer(sPackets);
boolean bFilterOut = (sFilter.countTokens() > 0);
while (sFilter.hasMoreTokens()) {
String sToken = sFilter.nextToken();
if (sToken.equals("*") || sToken.equals(localName))
bFilterOut = false;
else if (sToken.charAt(0) == '-' && sToken.endsWith(localName))
break;
}
if (bFilterOut)
return null;
}
for (int i = 0; i < mFactories.size(); i++) {
ModelFactory mf = mFactories.get(i);
if (mf.isRootNode(this, uri, localName)) {
// JavaPort: look for duplicate models where the model doesn't support adding to an existing model.
if (!mf.getAllowAdd()) {
for (Node child = getFirstXFAChild(); child != null; child = child.getNextXFASibling()) {
if (child.getClassTag() == mf.meClassTag)
throw new ExFull(ResId.DuplicateModelLoadException, XFA.getAtom(mf.meClassTag));
}
}
Model model = mf.newModel(this, prevSibling, uri, localName, qName, attributes);
// JavaPort: If we loaded a model where the local name matches but the
// namespace wasn't supplied, the C++ implementation will fix this before
// the model is serialized.
if (uri == "")
model.setNeedsNSNormalize(true);
return model;
}
}
// No factory found, so create a Packet
Packet packet = new Packet(this, prevSibling);
packet.setXmlPeer(new ModelPeer(
parent == this ? (Element)getXmlPeer() : parent, null, // ignores prevSibling
uri, localName, qName,
attributes, packet));
packet.setDOMProperties(uri, localName, qName, null);
return packet;
}
else if (parent == null)
return null;
return super.createElement(parent, prevSibling, uri, localName, qName, attributes, lineNumber, fileName);
}
/**
* @exclude from published api.
*/
public DependencyTracker dependencyTracker() {
return mDependencyTracker;
}
/**
* @exclude from published api.
*/
public void dependencyTracker(DependencyTracker oDependencyTracker) {
mDependencyTracker = oDependencyTracker;
}
/**
* @exclude from published api.
*/
public boolean getAllowThirdPartyXml() {
return mbAllowThirdPartyXml;
}
/**
* Returns the list of registered factories.
* @return a list of Model factories.
*/
public List factories() {
return mFactories;
}
/**
* get an attribute value, will return the default attribute value
* if none exist NON validating
* @exclude from published api.
*/
public Attribute getAttribute(int eAttributeTag) {
assert (eAttributeTag == XFA.TIMESTAMPTAG
|| eAttributeTag == XFA.UUIDTAG);
String aPropertyName = XFA.getAtom(eAttributeTag);
//
// Caution: timestamp and uuid attributes aren't schema attributes in XFA4J.
//
int attr = findAttr(null, aPropertyName);
String oAttrValue = "";
if (attr != -1)
oAttrValue = getAttrVal(attr);
return new StringAttr(aPropertyName,oAttrValue);
}
/**
* @exclude from published api.
*/
public String getBaseNS() {
return STRS.XDP_NAMESPACE;
}
/**
* @exclude from published api.
*/
public ScriptDynamicPropObj getDynamicScriptProp(String sPropertyName,
boolean bPropertyOverride,
boolean bPeek) {
// bPropertyOverride(#sPropertyName) means don't hunt for child nodes by name
// only get xfaproperty or child element(based on classname) or script property
if (!bPropertyOverride) {
if (AppModelScript.getPseudoModelFunc(this, null, sPropertyName))
return getPseudoModelPropObj;
}
return super.getDynamicScriptProp(sPropertyName, bPropertyOverride, bPeek);
}
private final static ScriptDynamicPropObj getPseudoModelPropObj =
new ScriptDynamicPropObj(Schema.XFAVERSION_10, Schema.XFAAVAILABILITY_ALL) {
public boolean invokeGetProp(Obj scriptThis, Arg retValue, String sPropertyName) {
return AppModelScript.getPseudoModelFunc(scriptThis, retValue, sPropertyName);
}
};
/**
* Gets all the context nodes that correspond to entries in the error list.
*
* @return A list of Element objects where the load discovered a problem.
*/
public List getErrorContextList() {
List errList = new ArrayList(super.getErrorContextList());
Node child = getFirstXFAChild();
// Append errors of child models
while (child != null) {
if (child instanceof Model) {
Model model = (Model)child;
errList.addAll(model.getErrorContextList());
}
child = child.getNextXFASibling();
}
return errList;
}
/**
* Gets all the errors that have been generated by this app model
* since the last method call to clear the error list.
* This involves getting the error lists for all
* the descendant models and concatenating them together.
* @return the current list of {@link ExFull} error objects.
*/
public List getErrorList() {
List errList = new ArrayList(super.getErrorList());
Node child = getFirstXFAChild();
// Append errors of child models
while (child != null) {
if (child instanceof Model) {
Model model = (Model)child;
errList.addAll(model.getErrorList());
}
child = child.getNextXFASibling();
}
return errList;
}
/**
* the EventManager manages xfe:script scripts and their
* associated events (ie. events that cause the scripts to execute)
* @exclude from public api.
*/
public EventManager getEventManager() {
return mEventManager;
}
/**
* Determines whether external proto fragments are marked as transient when
* they are resolved. When proto fragments are marked as transient, the
* {@link DOMSaveOptions#setSaveFragment(boolean)} setting controls whether
* resolved fragments are included when the model is serialized. The default
* is false
which means that resolved fragments are always
* serialized.
*
* This flag is only relevant if
* {@link AppModel#setHrefHandler(HrefHandler)} has been called.
*
* @return true
if external fragments should be transient (i.e.
* left as references when serialized), or false
if
* they should be non-transient (i.e. expanded when serialized).
* @see AppModel#setExternalProtosAreTransient(boolean)
*/
public boolean getExternalProtosAreTransient() {
return mbExternalProtosAreTransient;
}
/**
* return the fragment search path.
* @return an array of File objects
* @exclude
*/
public List getFragmentSearchPath() {
return moFragmentSearchPath;
}
/**
* @exclude from published api.
*/
public String getHeadNS() {
return STRS.XDP_NAMESPACE;
}
/**
* Gets the current HrefService
handler.
* @return the HrefService
handler associated with the AppModel
.
*/
public HrefHandler getHrefHandler() {
return mHrefHandler;
}
/**
* indicate whether this AppModel is used as a source for template fragments
* @return true if a fragment source
* @exclude
*/
public boolean getIsFragmentDoc() {
return mbIsFragmentDoc;
}
/**
* @see Model#getLegacySetting(AppModel.LegacyMask)
* @exclude from published api.
*/
public boolean getLegacySetting(LegacyMask nLegacyFlag) {
// Most legacy flags are handled by the template model, but the v30-scripting flag
// can be overridden by the form model. (While it's tempting to think of the mergeMode
// flag as also being part of the template, the data picks which one of possibly many
// top-level subforms are instantiated, so we only know *which* mergeMode flag will be
// in control when we have a form DOM.)
if (nLegacyFlag == XFA_LEGACY_V30_SCRIPTING) {
FormModel formModel = (FormModel)Model.getNamedModel(this, XFA.FORM);
if (formModel != null && formModel.mergeMode() == EnumAttr.MERGEMODE_MATCHTEMPLATE)
return false;
}
TemplateModel oTemplateModel = (TemplateModel)Model.getNamedModel(this, XFA.TEMPLATE);
if (oTemplateModel == null)
return false;
else
return oTemplateModel.getLegacySetting(nLegacyFlag);
}
/**
* Get the XFALogMessenger object.The XFALogMessenger object can be used to add or delete
* to the XFALogMessageHandlers active with the AppModel.
*
* @exclude from published api.
*/
public LogMessenger getLogMessenger() {
return mMessenger;
}
/**
* @see Element#getNS()
*
* @exclude from published api.
*/
public String getNS() {
// JavaPort: This method is defined for AppModel in Java but not C++.
// However, it *should* be defined in C++
// The Model version of this method adds a version number to the namespace.
// But the XDP namespace is version-number-free.
return getBaseNS();
}
/**
* @exclude from published api.
*/
public int getOutputBelow() {
return meOutputBelow;
}
/**
* Gets the list of XFA packets to filter.
* @return the packet list.
*
* @exclude from published api.
*/
public String getPacketList() {
return msPackets;
}
/**
* @see Node#getPreviousXMLSibling()
*
* @exclude from published api.
*/
public Node getPreviousXMLSibling() {
Element parent = getDocument();
if (parent == null)
return null;
Node child = parent.getFirstXMLChild();
Node prev = null;
while (child != null) {
if (child == this)
return prev;
prev = child;
child = child.getNextXMLSibling();
}
return null;
}
/**
* @exclude from published api.
*/
boolean getResolveAllExternalProtos() {
return mbResolveAllExternalProtos;
}
/**
* @exclude from published api.
*/
public int getSchemaType(int eTag) {
Node oChild = getFirstXFAChild();
while (oChild != null) {
if (oChild.getClassTag() == eTag)
return CHILD;
oChild = oChild.getNextXFASibling();
}
return super.getSchemaType(eTag);
}
/**
* Gets the list of script handlers registered with this app model.
* @return the list of script handlers.
* @see #addScriptHandler(ScriptHandler).
*/
public List getScriptHandlers() {
return mScriptHandlers;
}
/**
* Gets the script handler associated with the given language.
* @param sLanguageName the language name
* (without any "application/x-" prefix).
* @return the script handler registered for the specified language,
* or null if no handler has been registered for that language.
* @see #addScriptHandler(ScriptHandler).
*/
ScriptHandler getScriptHandler(String sLanguageName) {
for (int i = 0; i < mScriptHandlers.size(); i++) {
ScriptHandler scriptHandler = mScriptHandlers.get(i);
if (scriptHandler.languageName().equals(sLanguageName))
return scriptHandler;
}
return null;
}
/**
* @exclude from published api.
*/
public ScriptTable getScriptTable() {
return AppModelScript.getScriptTable();
}
/**
* @exclude from published api.
*/
int getSourceAbove() {
return meSourceAbove;
}
/**
* @see Model#getSourceBelow()
* @exclude
*/
public int getSourceBelow() {
return meSourceBelow;
}
/**
* Retrieves the current node, which is the starting node for calls to
* resolveNode()
and resolveNodes()
. This
* method is IDENTICAL to Model::getContext
. It is
* provided here for consistency with the scripting interface, which
* will provide a "this" property representing the current node.
* @return the current node.
*
* @exclude from published api.
*/
Node getThis() {
// getContext is implemented in XFAModelImpl. "getThis" is
// an alias for "getContext" for an AppModel.
return getContext();
}
/**
* @exclude from published api.
*/
public int getVersionRestriction() {
return mnMaxVersionAllowed;
}
/** @exclude from published api. */
public boolean getWillDirty() {
Document document = getDocument();
// If this node is not attached to a document yet, then assume that
// we are currently loading, so it won't dirty the doc. Actually appending
// the node to the document should cause dirtying if necessary.
if (document == null)
return false;
return document.getWillDirty();
}
/**
* @see Element#insertChild(Node, Node, boolean)
*/
public void insertChild(Node newChild, Node refChild, boolean bValidate) {
// Overwritten to facilitate the adding of other models to an app model
assert (null != newChild);
if (newChild instanceof Model) {
Model newModel = (Model)newChild;
super.insertChild(newModel, refChild, bValidate);
newModel.setAppModel(this);
}
else
super.insertChild(newChild, refChild, bValidate);
}
/**
* @see Element#isValidAttr(int, boolean, String)
*
* @exclude from published api.
*/
public boolean isValidAttr(int eTag, boolean bReport /* = false */, String value /* = null */) {
if (eTag == XFA.TIMESTAMPTAG || eTag == XFA.UUIDTAG)
return true;
return false;
}
/**
* @see Element#isValidChild(int, int, boolean, boolean)
*
* @exclude from published api.
*/
public boolean isValidChild(int eTag, int nError, boolean bBeforeInsert, boolean bOccurrenceErrorOnly) {
if (eTag == XFA.PACKETTAG)
return true;
return super.isValidChild(eTag, nError, bBeforeInsert, bOccurrenceErrorOnly);
}
/**
* Is this element the root node of an XDP document.
* @param uri the namespace of this element
* @param localName the local name of this element
* @param qName the qualified name of this element
* @return boolean true if this is the root node of XDP
*
* @exclude from published api.
*/
@FindBugsSuppress(code="ES")
public boolean isXFANode(String uri, String localName, String qName) {
if (localName == XFA.XFA) {
// If the namespace is either empty or one of our XFA namespaces,
// accept the node.
if (uri == "" || uri.startsWith(Node.gsXFANamespacePrefix))
return true;
}
else if (localName == XFA.XDP) {
// Accept
if (uri != "" && uri.startsWith(STRS.XDP_NAMESPACE))
return true;
}
return false;
}
/**
* Is the given element the root node of an XDP document.
*
* @exclude from published api.
*/
public static boolean isXFANode(Element node) {
String localName = node.getName();
if (localName == XFA.XFA) {
// If the namespace is either empty or one of our XFA namespaces,
// accept the node.
String uri = node.getNS();
if (uri == "" || uri.startsWith(Node.gsXFANamespacePrefix))
return true;
// JavaPort_DATA: For now, because of the single DOM architecture
// we also have to accept
// This may need to be removed if ever we stop relabelling
// nodes to
if (uri != "" && uri.startsWith(STRS.XDP_NAMESPACE))
return true;
}
else if (localName == XFA.XDP) {
// Accept
String uri = node.getNS();
if (uri != "" && uri.startsWith(STRS.XDP_NAMESPACE))
return true;
}
return false;
}
/**
* Looks up a scripting object registered with the global scripting namespace.
* @param sShortCutName the scripting shortcut name.
* @return a scripting object (typically derived from PseudoModel
), or
* null
if not found.
*/
public Obj lookupPseudoModel(String sShortCutName) {
return mExtraShortCuts.get(sShortCutName);
}
/**
* Creates a new node hierarchy of a new XFA DOM. The returned node
* will always be the AppModel
. The children that this
* node has depends on which factories have been added via
* addFactory()
.
* Each installed factory will create some default node or tree of nodes
* under the AppModel
node.
* @return The root node of the new hierarchy.
*/
public Element newDOM() {
while (getFirstXFAChild() != null)
getFirstXFAChild().remove();
mEventManager.reset();
// Unlike the C++, we don't create a new document here,
// but the existing one is cleared out.
Document doc = getDocument();
while (doc.getFirstXMLChild() != null)
doc.getFirstXMLChild().remove();
doc.isDefaultDocument(false);
// Reset the DOM peer
ModelPeer xmlPeer = new ModelPeer(doc, null, "", XFA.XFA, XFA.XFA, null, this);
xmlPeer.setModel(this);
setXmlPeer(xmlPeer);
createDOM((Element)this.getXmlPeer());
// JavaPort: unlike the C++, we don't call loadNode on each child since
// any Model children have been fully created by this point.
return this;
}
/**
* @see Model#postLoad
*
* @exclude from published api.
*/
protected void postLoad() {
//
// Javaport: new for Java. If a packet handler was specified
// then invoke its filter'er.
//
if (mPacketHandler != null) {
Node child = getFirstXMLChild();
while (child != null) {
Node nextChild = child.getNextXMLSibling();
mPacketHandler.filterPackets(child, mHandlerData);
child = nextChild;
}
}
}
/**
* @see Node#preSave(boolean)
*
* @exclude from published api.
*/
public void preSave(boolean bSaveXMLScript) {
// Apply preSave to children
Node child = getFirstXFAChild();
while (child != null) {
child.preSave(bSaveXMLScript);
child = child.getNextXFASibling();
}
}
/**
* @exclude from published api.
*/
public boolean ready(boolean bForced /* = false */) {
boolean bRet = false;
// apply the ready() call to all child models
for (Node child = getFirstXFAChild(); child != null; child = child.getNextXFASibling()) {
if (child instanceof Model) {
Model model = (Model)child;
bRet |= model.ready(bForced);
}
}
return bRet;
}
/**
* @exclude from published api.
*/
void preSaveXML() {
// JavaPort TODO: Probably need to use reflection to handle this?
// if (mpPreSaveXMLCallback != null)
// mpPreSaveXMLCallback(mpPreSaveXMLData);
}
/**
* @see com.adobe.xfa.Model#publish(com.adobe.xfa.Model.Publisher)
* @exclude from published api.
*/
public boolean publish(Publisher publisher) {
boolean bRet = true;
// recursively publish all child models
for (Node child = getFirstXFAChild(); child != null; child = child.getNextXFASibling()) {
if (child instanceof Model) {
bRet &= ((Model)child).publish(publisher);
}
}
return bRet;
}
/**
* Removes a scripting object shortcut from the
* global scripting namespace.
* @param sShortCutName the shortcut name of a scripting object
* @see #addPseudoModel(String, Obj)
*/
public void removePseudoModel(String sShortCutName) {
mExtraShortCuts.remove(sShortCutName);
}
void resetPseudoModelEvents() {
for (Obj obj : mExtraShortCuts.values()) {
EventManager.resetEventTable(obj.getEventTable(false));
}
}
/**
* @exclude from published api.
*/
void setAllowThirdPartyXml(boolean bAllowThirdPartyXml) {
mbAllowThirdPartyXml = bAllowThirdPartyXml;
}
/**
* Sets the value of an attribute
*
* @exclude from published api.
*/
public void setAttribute(Attribute oValue, int eAttributeTag) {
if (eAttributeTag == XFA.TIMESTAMPTAG || eAttributeTag == XFA.UUIDTAG) {
updateAttribute(oValue);
}
else {
MsgFormat oMessage = new MsgFormat(ResId.InvalidSetPropertyException);
oMessage.format(getClassAtom());
oMessage.format(oValue.getLocalName());
throw new ExFull(oMessage);
}
}
/**
* Determines whether external proto fragments are marked as transient when
* they are resolved. When proto fragments are marked as transient, the
* {@link DOMSaveOptions#setSaveFragment(boolean)} setting controls whether
* resolved fragments are included when the model is serialized. The default
* is false
which means that resolved fragments are always
* serialized.
*
* This flag is only relevant if
* {@link AppModel#setHrefHandler(HrefHandler)} has been called.
*
* @param bExternalProtosAreTransient
* true
if external fragments should be transient
* (i.e. left as references when serialized), or
* false
if they should be non-transient (i.e.
* expanded when serialized).
* @see #getExternalProtosAreTransient()
* @see #setHrefHandler(HrefHandler)
*/
public void setExternalProtosAreTransient(boolean bExternalProtosAreTransient) {
mbExternalProtosAreTransient = bExternalProtosAreTransient;
}
/**
* Set the fragment search path.
* @param oSearchPath fragment search path
* @exclude
*/
public void setFragmentSearchPath(List oSearchPath) {
moFragmentSearchPath = oSearchPath;
}
/**
* Sets the HrefService
handler associated with this AppModel
.
* @param handler the HrefService
handler.
*
* The href service handles the URL resolution and fragment loading for all
* usehref attribute values on ProtoableNode
s.
*/
public void setHrefHandler(HrefHandler handler) {
mHrefHandler = handler;
}
/**
* flag this AppModel as being a source for template fragments (or not)
* @param bIsFragmentDoc true if this is a source for template fragments.
* @exclude
*/
public void setIsFragmentDoc(boolean bIsFragmentDoc) {
mbIsFragmentDoc = bIsFragmentDoc;
}
/**
* Set the XFALogMessenger object. The LogMessenger object can be used
* to replace all of the currently attached LogMessengers.
*
* @exclude from published api.
*/
void setLogMessenger(LogMessenger oMessenger) {
if (oMessenger == null)
return;
if (mMessenger == oMessenger)
return;
if (oMessenger != null) {
List oMessages = mMessenger.storedMsgArray();
for (int i = 0; i < oMessages.size(); i++) {
LogMessage oMessage = oMessages.get(i);
oMessenger.sendMessage(oMessage);
}
}
mMessenger = oMessenger;
}
/**
* Sets this app model's packet handler.
* @param oPacketHandler a packet handler.
* @param oHandlerData some handler data.
*
* @exclude from published api.
*/
public void setPacketHandler(PacketHandler oPacketHandler,
Object oHandlerData) {
mPacketHandler = oPacketHandler;
mHandlerData = oHandlerData;
}
/**
* Sets the list of XFA packets to filter.
* @param sPackets the packet list.
*
* @exclude from published api.
*/
public void setPacketList(String sPackets) {
msPackets = sPackets;
}
/**
* @exclude from published api.
*/
public void setResolveAllExternalProtos(boolean bResolveAllExternalProtos) {
mbResolveAllExternalProtos = bResolveAllExternalProtos;
}
/**
* @exclude from published api.
*/
public void setSourceAbove(int eSouceAbove) {
meSourceAbove = eSouceAbove;
}
/**
* @exclude from published api.
*/
public void setSourceBelow(int eSouceBelow) {
meSourceBelow = eSouceBelow;
}
/**
* @exclude from published api.
*/
public void setVersionRestriction(int nVersion, int eOutputBelow) {
mnMaxVersionAllowed = nVersion;
meOutputBelow = eOutputBelow;
}
/** @exclude from published api. */
public void setWillDirty(boolean bWillDirty) {
getDocument().setWillDirty(bWillDirty);
}
/**
* Get a boolean that indicates if the originalXFAVersion processing
* instruction should be updated when each XFA Model child is saved.
*
* @return TRUE if the processing instruction should be updated, otherwise
* FALSE.
* This function is only for Designer so when they create a
* new document they can avoid creating the originalXFAVersion.
*
* @exclude from published api.
*/
public boolean updateOriginalVersion() {
return mbUpdateOriginalVersion;
}
/**
* Set a boolean that indicates if the originalXFAVersion processing
* instruction should be updated when each XFA Model child is saved.
*
* @param bUpdate -
* TRUE if the processing instruction should be updated,
* otherwise FALSE.
* This function is only for Designer so when they create a
* new document they can avoid creating the originalXFAVersion.
*
* @exclude from published api.
*/
public void updateOriginalVersion(boolean bUpdate) {
mbUpdateOriginalVersion = bUpdate;
}
}