All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.localeset.LocaleSetModel Maven / Gradle / Ivy

There is a newer version: 2024.11.18751.20241128T090041Z-241100
Show newest version
/*
 * 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.localeset;

import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.adobe.xfa.AppModel;
import com.adobe.xfa.Attribute;
import com.adobe.xfa.Element;
import com.adobe.xfa.EnumAttr;
import com.adobe.xfa.EnumValue;
import com.adobe.xfa.LogMessage;
import com.adobe.xfa.Model;
import com.adobe.xfa.Node;
import com.adobe.xfa.STRS;
import com.adobe.xfa.Schema;
import com.adobe.xfa.StringAttr;
import com.adobe.xfa.TextNode;
import com.adobe.xfa.XFA;
import com.adobe.xfa.protocol.ProtocolUtils;
import com.adobe.xfa.service.storage.XMLStorage;
import com.adobe.xfa.template.TemplateModel;
import com.adobe.xfa.ut.ExFull;
import com.adobe.xfa.ut.FindBugsSuppress;
import com.adobe.xfa.ut.LcData;
import com.adobe.xfa.ut.LcLocale;
import com.adobe.xfa.ut.MsgFormatPos;
import com.adobe.xfa.ut.Numeric;
import com.adobe.xfa.ut.Peer;
import com.adobe.xfa.ut.PictureFmt;
import com.adobe.xfa.ut.ResId;
import com.adobe.xfa.ut.StringHolder;
import com.adobe.xfa.ut.StringUtils;

/**
 * A class to model the collection of all XFA nodes that make up
 * form locale set.
 */
public final class LocaleSetModel extends Model {

	//
	// Store away for key attribute values.
	//
	private static final int[] geDateTimePats = {
			EnumAttr.PATTERN_FULL,
			EnumAttr.PATTERN_LONG,
			EnumAttr.PATTERN_MED,
			EnumAttr.PATTERN_SHORT
	};

	private static final int[] geNumPats = {
			EnumAttr.PATTERN_NUMERIC,
			EnumAttr.PATTERN_CURRENCY,
			EnumAttr.PATTERN_PERCENT
	};

	private static final LocaleSetSchema gLocaleSchema = new LocaleSetSchema();

	private static final String gsAmbient = "ambient";

	/**
	 * @see Model#createNode(int, Element, String, String, boolean)
	 *
	 * @exclude from published api.
	 */
	@FindBugsSuppress(code="ES")
	public Node createNode(int eTag, Element parent, String aName, String aNS, boolean bDoVersionCheck) {
		assert (aName != null);
		assert (aNS != null);
		Element retVal = getSchema().getInstance(eTag, this, parent, null, bDoVersionCheck);
		if (aName != "") {
			retVal.setName(aName);
		}
		return retVal;
	}

	/**
	 * @see Model#getBaseNS()
	 *
	 * @exclude from published api.
	 */
	public String getBaseNS() {
	    return STRS.XFALOCALESETNS;
	}
	
	/**
	 * @exclude from published api.
	 */
	public String getHeadNS() {
		return localeSetNS();
	}

	/**
	 * Gets the locale set model held within an XFA DOM hierarchy.
	 * 
	 * @param appModel the application model.
	 * @param bCreateIfNotFound when set, create a model if necessary.
	 * @return the locale set model or null if none found.
	 */
	public static LocaleSetModel getLocaleSetModel(AppModel appModel,
								boolean bCreateIfNotFound /* = false */) {
		
		LocaleSetModel lsm = (LocaleSetModel)Model.getNamedModel(appModel, XFA.LOCALESET);

		if (bCreateIfNotFound && lsm == null) {
			LocaleSetModelFactory factory = new LocaleSetModelFactory();
			lsm = (LocaleSetModel) factory.createDOM((Element)appModel.getXmlPeer());
			lsm.setDocument(appModel.getDocument());
			
			appModel.notifyPeers(Peer.CHILD_ADDED, XFA.LOCALESET, lsm);
		}
		return lsm;
	}

	/**
	 * @exclude from published api.
	 */
	protected static Schema getModelSchema() {
		return gLocaleSchema;
	}

	/**
	 * Namespace
	 * 
	 * @return The localeSet namespace URI string.
	 *
	 * @exclude from published api.
	 */
	public static String localeSetNS() {
		return STRS.XFALOCALESETNS_CURRENT;
	}

	/**
	 * Convenience method to update the LocaleSetModel held within the DOM
	 * hierarchy. Search the given root node for the locale attribute off
	 * subform and field nodes. Augment the locale set model with the data
	 * of all new locales found from this search.
	 * 
	 * @param oAppModel -
	 *            the application model.
	 * @param oNode -
	 *            the root node of the template model.
	 * @return boolean true upon success and false otherwise.
	 *
	 * @exclude from published api.
	 */
	public static boolean setLocaleSetModel(AppModel oAppModel, Element oNode) {
		//
		// Search the template root node and collect all locale names.
		//
		List oLocales = new ArrayList();
		find(oNode, oLocales);
		//
		// If none found Then bail out.
		//
		if (oLocales.size() == 0)
			return true;
		//
		// Get the localeSetModel (creating it if necessary), and find all
		// locales in locale set model.
		//
		LocaleSetModel oModel = LocaleSetModel.getLocaleSetModel(oAppModel,
				true);
		List oLsLocales = new ArrayList();
		find(oModel, oLsLocales);
		//
		// Filter all localeSet locales from those found in template.
		//
		int n = oLsLocales.size();
		for (int i = oLocales.size(); i > 0; i--) {
			for (int j = 0; j < n; j++) {
				if (oLsLocales.get(j) == oLocales.get(i - 1)) {
					oLocales.remove(i - 1);
					break;
				}
			}
		}
		int nLocales = oLocales.size();
		//
		// If nothing new found Then bail out.
		//
		if (nLocales == 0)
			return true;
		//
		// Create some localeSet node that we can then clone.
		//
		Element oLocaleSym = oModel.createElement(null, null, null,
				XFA.LOCALE, XFA.LOCALE, null, 0, null);
		Element oCalendarSyms = oModel.createElement(null, null, null,
				XFA.CALENDARSYMBOLS, XFA.CALENDARSYMBOLS, null, 0, null);
		Element oMonthNames = oModel.createElement(null, null, null,
				XFA.MONTHNAMES, XFA.MONTHNAMES, null, 0, null);
		Element oDayNames = oModel.createElement(null, null, null,
				XFA.DAYNAMES, XFA.DAYNAMES, null, 0, null);
		Element oMeridiemNames = oModel.createElement(null, null, null,
				XFA.MERIDIEMNAMES, XFA.MERIDIEMNAMES, null, 0, null);
		Element oEraNames = oModel.createElement(null, null, null,
				XFA.ERANAMES, XFA.ERANAMES, null, 0, null);
		Element oDatePats = oModel.createElement(null, null, null,
				XFA.DATEPATTERNS, XFA.DATEPATTERNS, null, 0, null);
		Element oTimePats = oModel.createElement(null, null, null,
				XFA.TIMEPATTERNS, XFA.TIMEPATTERNS, null, 0, null);
		Element oDateTimeSym = oModel.createElement(null, null, null,
				XFA.DATETIMESYMBOLS, XFA.DATETIMESYMBOLS, null, 0, null);
		Element oNumPats = oModel.createElement(null, null, null,
				XFA.NUMBERPATTERNS, XFA.NUMBERPATTERNS, null, 0, null);
		Element oNumSyms = oModel.createElement(null, null, null,
				XFA.NUMBERSYMBOLS, XFA.NUMBERSYMBOLS, null, 0, null);
		Element oCurSyms = oModel.createElement(null, null, null,
				XFA.CURRENCYSYMBOLS, XFA.CURRENCYSYMBOLS, null, 0, null);
		Element oTypefaces = oModel.createElement(null, null, null,
				XFA.TYPEFACES, XFA.TYPEFACES, null, 0, null);
		//
		// Foreach locale in list Do...
		//
		Model model = oLocaleSym.getModel();
		boolean bLocalesOk = true;
		for (int i = 0; i < nLocales; i++) {
			//
			// Normalize the locale's name.
			//
			String sLocale = (String) oLocales.get(i);
			LcLocale oLocale = new LcLocale(sLocale);
			//
			// If we don't have data for locale Then skip it.
			//
			if (!oLocale.isValid()) {
				MsgFormatPos oMessage = new MsgFormatPos(ResId.LocaleUnknown);
				oMessage.format(sLocale);
				ExFull oErr = new ExFull(oMessage.resId(), oMessage.toString());
				model.addErrorList(oErr, LogMessage.MSG_WARNING, oNode);
				bLocalesOk = false;
				continue;
			}
			LcData oLcData = new LcData(oLocale.getIsoName());
			//
			// Create the node:
			//
			// 
			// ...
			// 
			//
			Element oLocaleSymClone = oLocaleSym.clone(null, true);
			Attribute oProp = new StringAttr(XFA.NAME, oLocale.getIsoName());
			oLocaleSymClone.setAttribute(oProp, XFA.NAMETAG);
			String sDesc = "" /* oLocale.getDescName() */;
			if (!StringUtils.isEmpty(sDesc)) {
				oProp = new StringAttr(XFA.DESC, sDesc);
				oLocaleSymClone.setAttribute(oProp, XFA.DESCTAG);
			}
			oModel.appendChild(oLocaleSymClone, false);
			//
			// Create the node:
			//
			// 
			// ...
			// 
			//
			Element oCalendarSymsClone = oCalendarSyms.clone(null, true);
			oProp = new StringAttr(XFA.NAME, "gregorian");
			oCalendarSymsClone.setAttribute(oProp, XFA.NAMETAG);
			oLocaleSymClone.appendChild(oCalendarSymsClone, false);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// 
			//
			Element oMonthNamesClone = oMonthNames.clone(null, true);
			for (int j = LcData.JAN; j <= LcData.DEC; j++) {
				Element oMonth = oMonthNamesClone.getElement(XFA.MONTHTAG, j);
				TextNode tval = oMonth.getText(false, true, false);
				tval.setValue(oLcData.getMonthName(j), true, false);
			}
			oCalendarSymsClone.appendChild(oMonthNamesClone, false);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// 
			//
			oMonthNamesClone = oMonthNames.clone(null, true);
			oProp = new StringAttr(XFA.ABBR, "1");
			oMonthNamesClone.setAttribute(oProp, XFA.ABBRTAG);
			for (int j = LcData.JAN; j <= LcData.DEC; j++) {
				Element oMonth = oMonthNamesClone.getElement(XFA.MONTHTAG, j);
				TextNode tval = oMonth.getText(false, true, false);
				tval.setValue(oLcData.getAbbrMonthName(j), true, false);
			}
			oCalendarSymsClone.appendChild(oMonthNamesClone, false);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// 
			//
			Element oDayNamesClone = oDayNames.clone(null, true);
			for (int j = LcData.SUN; j <= LcData.SAT; j++) {
				Element oDay = oDayNamesClone.getElement(XFA.DAYTAG, j);
				TextNode tval = oDay.getText(false, true, false);
				tval.setValue(oLcData.getWeekDayName(j), true, false);
			}
			oCalendarSymsClone.appendChild(oDayNamesClone, false);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// 
			//
			oDayNamesClone = oDayNames.clone(null, true);
			oProp = new StringAttr(XFA.ABBR, "1");
			oDayNamesClone.setAttribute(oProp, XFA.ABBRTAG);
			for (int j = LcData.SUN; j <= LcData.SAT; j++) {
				Element oDay = oDayNamesClone.getElement(XFA.DAYTAG, j);
				TextNode tval = oDay.getText(false, true, false);
				tval.setValue(oLcData.getAbbrWeekdayName(j), true, false);
			}
			oCalendarSymsClone.getNodes().append(oDayNamesClone);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// 
			//
			Element oMeridiemNamesClone = oMeridiemNames.clone(null, true);
			for (int j = LcData.AM; j <= LcData.PM; j++) {
				Element oMeri
				    = oMeridiemNamesClone.getElement(XFA.MERIDIEMTAG, j);
				TextNode tval = oMeri.getText(false, true, false);
				tval.setValue(oLcData.getMeridiemName(j), true, false);
			}
			oCalendarSymsClone.getNodes().append(oMeridiemNamesClone);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// 
			//
			Element oEraNamesClone = oEraNames.clone(null, true);
			for (int j = LcData.BC; j <= LcData.AD; j++) {
				Element oEra = oEraNamesClone.getElement(XFA.ERATAG, j);
				TextNode tval = oEra.getText(false, true, false);
				tval.setValue(oLcData.getEraName(j), true, false);
			}
			oCalendarSymsClone.getNodes().append(oEraNamesClone);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// ...
			// 
			//
			Element oDatePatsClone = oDatePats.clone(null, true);
			for (int j = LcData.FULL; j <= LcData.SHORT; j++) {
				Element oPat = oDatePatsClone.getElement(XFA.DATEPATTERNTAG, j);
				oProp = EnumValue.getEnum(XFA.NAMETAG, EnumAttr.getEnum(geDateTimePats[j]));
				oPat.setAttribute(oProp, XFA.NAMETAG);
				TextNode tval = oPat.getText(false, true, false);
				tval.setValue(oLcData.getDateFormat(LcData.SHORT - j + 1), true, false);
			}
			oLocaleSymClone.getNodes().append(oDatePatsClone);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// ...
			// 
			//
			Element oTimePatsClone = oTimePats.clone(null, true);
			for (int j = LcData.FULL; j <= LcData.SHORT; j++) {
				Element oPat = oTimePatsClone.getElement(XFA.TIMEPATTERNTAG, j);
				oProp = EnumValue.getEnum(XFA.NAMETAG, EnumAttr.getEnum(geDateTimePats[j]));
				oPat.setAttribute(oProp, XFA.NAMETAG);
				TextNode tval = oPat.getText(false, true, false);
				tval.setValue(oLcData.getTimeFormat(LcData.SHORT - j + 1), true, false);
			}
			oLocaleSymClone.getNodes().append(oTimePatsClone);
			//
			// Create node:
			//
			// ...
			//
			Element oDateTimeClone = oDateTimeSym.clone(null, true);
			TextNode tval = oDateTimeClone.getText(false, true, false);
			tval.setValue(oLcData.getDateTimePattern(), true, false);
			oLocaleSymClone.getNodes().append(oDateTimeClone);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// 
			//
			Element oNumPatsClone = oNumPats.clone(null, true);
			for (int j = LcData.NUMERIC; j <= LcData.PERCENT; j++) {
				Element oPat = oNumPatsClone
						.getElement(XFA.NUMBERPATTERNTAG, j);
				oProp = EnumValue.getEnum(XFA.NAMETAG, EnumAttr.getEnum(geNumPats[j]));
				oPat.setAttribute(oProp, XFA.NAMETAG);
				tval = oPat.getText(false, true, false);
				tval.setValue(oLcData.getNumericFormat(j), true, false);
			}
			oLocaleSymClone.getNodes().append(oNumPatsClone);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// ...
			// ...
			// 
			//
			Element oNumSymsClone = oNumSyms.clone(null, true);
			for (int j = LcData.NUM_DECIMAL; j <= LcData.NUM_ZERO; j++) {
				String sSymbol;
				int eTag;
				if (j == LcData.NUM_DECIMAL) {
					sSymbol = oLcData.getRadixSymbol();
					eTag = EnumAttr.NUMERIC_DECIMAL;
				} else if (j == LcData.NUM_GROUPING) {
					sSymbol = oLcData.getGroupingSymbol();
					eTag = EnumAttr.NUMERIC_GROUPING;
				} else if (j == LcData.NUM_PERCENT) {
					sSymbol = oLcData.getPercentSymbol();
					eTag = EnumAttr.NUMERIC_PERCENT;
				} else if (j == LcData.NUM_MINUS) {
					sSymbol = oLcData.getNegativeSymbol();
					eTag = EnumAttr.NUMERIC_MINUS;
				} else /* if (j == LcData.NUM_ZERO) */{
					sSymbol = oLcData.getZeroSymbol();
					eTag = EnumAttr.NUMERIC_ZERO;
				}
				Element oSym = oNumSymsClone.getElement(XFA.NUMBERSYMBOLTAG, j);
				oProp = EnumValue.getEnum(XFA.NAMETAG, EnumAttr.getEnum(eTag));
				oSym.setAttribute(oProp, XFA.NAMETAG);
				tval = oSym.getText(false, true, false);
				tval.setValue(sSymbol, true, false);
			}
			oLocaleSymClone.getNodes().append(oNumSymsClone);
			//
			// Create the nodes:
			//
			// 
			// ...
			// ...
			// ...
			// 
			//
			Element oCurSymsClone = oCurSyms.clone(null, true);
			for (int j = LcData.CUR_SYMBOL; j <= LcData.CUR_DECIMAL; j++) {
				String sSymbol;
				int eTag;
				if (j == LcData.CUR_SYMBOL) {
					sSymbol = oLcData.getCurrencySymbol();
					eTag = EnumAttr.CURRENCY_SYMBOL;
				} else if (j == LcData.CUR_ISONAME) {
					sSymbol = oLcData.getCurrencyName();
					eTag = EnumAttr.CURRENCY_ISONAME;
				} else /* if (j == LcData.CUR_DECIMAL) */{
					sSymbol = oLcData.getCurrencyRadix();
					eTag = EnumAttr.CURRENCY_DECIMAL;
				}
				Element oSym = oCurSymsClone.getElement(XFA.CURRENCYSYMBOLTAG, j);
				oProp = EnumValue.getEnum(XFA.NAMETAG, EnumAttr.getEnum(eTag));
				oSym.setAttribute(oProp, XFA.NAMETAG);
				tval = oSym.getText(false, true, false);
				tval.setValue(sSymbol, true, false);
			}
			oLocaleSymClone.getNodes().append(oCurSymsClone);
			//
			// Create the nodes:
			//
			// 
			//   
			// 
			//
			//Watson 1442022 - keep typefaces out until a later version
			Element oTypefacesClone = oTypefaces.clone(null, true);
			List oTypefaceList = oLcData.getTypefaces();
			for (int k = 0; k < oTypefaceList.size(); k++) {
        		Element oSym = oModel.createElement(null, null, null,
                				XFA.TYPEFACE, XFA.TYPEFACE, null, 0, null);
				oProp = new StringAttr(XFA.NAME, oTypefaceList.get(k));
				oSym.setAttribute(oProp, XFA.NAMETAG);
				oTypefacesClone.appendChild(oSym, false);
			}
			oLocaleSymClone.getNodes().append(oTypefacesClone);

		}
		return bLocalesOk;
	}

	/**
	 * Default Constructor.
	 *
	 * @exclude from published api.
	 */
	public LocaleSetModel(Element parent, Node prevSibling) {
		super(parent, prevSibling, localeSetNS(), XFA.LOCALESET,
				XFA.LOCALESET, STRS.DOLLARLOCALESET, XFA.LOCALESETTAG,
				XFA.LOCALESET, getModelSchema());
	}

	/**
	 * @see Model#postLoad()
	 *
	 * @exclude from published api.
	 */
	protected void postLoad() {
		refreshLocales();
	}

	/**
	 * Refresh the XFA API's runtime locale data from this model's localeSet.
	 * 
	 * Typically the localeSet will contain locales and/or locale data that is
	 * different from LcData's static store.
	 *
	 * @exclude from published api.
	 */
	public void refreshLocales() {
		Model oModel = getModel();
		for (Node oChild = getFirstXFAChild(); oChild != null;
										oChild = oChild.getNextXFASibling()) {
			//
			// Walk this localeSet model and assemble the locale data,
			// locale by locale.
			//
			LcData.LcRunTimeData oLcData;
			StringHolder sLoc = new StringHolder();
			try {
				oLcData = walk(oChild, sLoc, null);
				//
				// Ensure locale data is valid.
				//
				if (oLcData == null || StringUtils.isEmpty(oLcData.localeName)) {
					MsgFormatPos oMessage = new MsgFormatPos(ResId.LocaleUnknown);
					oMessage.format("");
					ExFull oErr = new ExFull(oMessage);
					oModel.addErrorList(oErr, LogMessage.MSG_WARNING, this);
					continue;
				}
				if (! LcData.validate(oLcData)) {
					MsgFormatPos oMessage = new MsgFormatPos(ResId.LocaleDataIncomplete);
					oMessage.format(oLcData.localeName);
					ExFull oErr = new ExFull(oMessage);
					oModel.addErrorList(oErr, LogMessage.MSG_WARNING, this);
					continue;
				}	
			} catch (ExFull oErr) {
				oModel.addErrorList(oErr, LogMessage.MSG_WARNING, this);
				continue;	
			}
			//
			// Update LcData's runtime data for this locale.
			//
			LcData.update(oLcData);
		}
	}

	/**
	 * @exclude from published api.
	 */
	public static void loadLocalesFromConfig(Node oContext) {
		//
		// Get common properties of interest from configuration.
		//
		String sLocaleSetPath = null;
		String sBasePath = null;
		String sUriPath = null;
		if (oContext != null) {
			//
			// Get any localeSet path.
			//
			Node oTree = oContext.resolveNode("localeSet");
			if (oTree != null && oTree.getXFAChildCount() == 1) {
				TextNode textNode = (TextNode) oTree.getFirstXFAChild();
				sLocaleSetPath = textNode.getValue();
			}
			//
			// Get any template base path.
			//
			sBasePath = ProtocolUtils.getTemplateBasePathFromConfig(oContext);
			//
			// Get any template uri path, remembering to strip away
			// the filename part of the path.
			//
			sUriPath = ProtocolUtils.getTemplateUriPathFromConfig(oContext);
		}
		//
		// If no localeSet path Then we're done.
		//
		if (StringUtils.isEmpty(sLocaleSetPath))
			return;
		//
		// The path may have a "|" instead of ":" for the drive so
		// replace it if neccessary.
		//
		//int nSlash = sLocaleSetPath.indexOf("|");
	// Javaport: TODO
	//	if (nSlash >= 0)
	//		sLocaleSetPath.setCharAt(nSlash, ':');
		//
		// Try resolving the url according to the base url.
		// Failing that, try the alternate url.  If we still
		// can't resolve it Then hurl.
		//
		InputStream isResolved = null;
		AppModel oTmpAppModel = new AppModel(null) ;
		try {
			StringHolder resolvedUrl = new StringHolder();
			isResolved = ProtocolUtils.checkUrl(sBasePath, sLocaleSetPath, true, resolvedUrl);
			if (isResolved == null)
				isResolved = ProtocolUtils.checkUrl(sUriPath, sLocaleSetPath, true, resolvedUrl);
			if (isResolved == null) {
				// Cannot resolve url [%1].
				MsgFormatPos oMsg = new MsgFormatPos(ResId.XFAHrefStoreException);
				oMsg.format(sLocaleSetPath);
				throw new ExFull(oMsg);
			}
			
			//
			// Install a localeSet factory into a temporary app model,
			// and read in the url into a memory stream.
			//			
			LocaleSetModelFactory oLocaleSetFactory = new LocaleSetModelFactory();
			oTmpAppModel.addFactory(oLocaleSetFactory);
			XMLStorage oXMLStorage = new XMLStorage();
			
			//
			// Load its localeSet model, populating LcLocale's and LcData's
			// runtime storage with its contents.
			//
			oXMLStorage.loadModel(oTmpAppModel, isResolved, resolvedUrl.value, "", null);
			
		}
		finally {
			try {
				if (isResolved != null) isResolved.close();
			}
			catch (IOException ex) {
			}
		}
		
		LocaleSetModel oLocaleSetModel = getLocaleSetModel(oTmpAppModel, false);
		
		//
		// Check for load warnings.
		//
		if (oLocaleSetModel != null
		&& oLocaleSetModel.getErrorList().size() > 0) {
			List errorList = oLocaleSetModel.getErrorList();
			for (int i = 0, n = errorList.size(); i < n; i++) {
				ExFull error = errorList.get(i);
				error.resolve();
				//String aError = error.toString();
			}
		}
	}
	
	/**
	 * @exclude from published api.
	 */
	public int getHeadVersion() {
		return Schema.XFAVERSION_LOCALESETHEAD;
	}
	
	/**
	 * @see Element#getNS()
	 * 
	 * @exclude from published api.
	 */
	public String getNS()  {
		
		int nVersion = getCurrentVersion();

		// Check if there is a template in the AppModel.  If so
		// then we want to set the version of the localeset
		// based on the template.
		AppModel appModel = getAppModel();
		if (appModel != null) {
			for (Node child = appModel.getFirstXFAChild(); child != null; child = child.getNextXFASibling()) {
				if (child instanceof TemplateModel) {
					nVersion = ((TemplateModel)child).getCurrentVersion();
					break;
				}
			}
		}

		// if we have a version set use it. 
		if (nVersion > 0) {
			// The ns version should never be higher than
			// the model head ns version
			if (nVersion > Schema.XFAVERSION_LOCALESETHEAD)
				nVersion = Schema.XFAVERSION_LOCALESETHEAD;
			
			// the ns stayed the same between 2.1 and 2.5
			if (nVersion <= Schema.XFAVERSION_25)
				nVersion = Schema.XFAVERSION_21;

			String sNS = getBaseNS();

			double dVersion = ((double)nVersion) / 10.0;

			sNS += Numeric.doubleToString(dVersion, 1, false);
			sNS += '/'; // add trailing '/'

			// generate an atom with the version.
			return sNS.intern();
		}
		
		return super.getNS();
	}
	
	/**
	 * @exclude from published api.
	 */
	public boolean isVersionCompatible(int nVersion, int nTargetVersion) {
		
		// locale 2.1 -> 2.5 are all the same namespace
		if (nVersion <= Schema.XFAVERSION_25)
			nVersion = Schema.XFAVERSION_25;
		if (nTargetVersion <= Schema.XFAVERSION_25)
			nTargetVersion = Schema.XFAVERSION_25;
		
		return super.isVersionCompatible(nVersion, nTargetVersion);
	}

	private static void find(Element oNode, List oLocales) {
		if (oNode == null)
			return;
		//
		// Check the locale attribute on subform, draw and field nodes
		// of the template model.
		//
		if (oNode.isSameClass(XFA.SUBFORMTAG)
				|| oNode.isSameClass(XFA.DRAWTAG)
					|| oNode.isSameClass(XFA.FIELDTAG)) {
			int eLocale = XFA.LOCALETAG;
			if (oNode.isPropertyValid(eLocale) &&
				oNode.isPropertySpecified(eLocale, true, 0)) {
				Attribute oAttr = oNode.getAttribute(eLocale);
				if (oAttr != null && ! oAttr.isEmpty()) {
					String sLocale = oAttr.toString();
					if (! sLocale.equals(gsAmbient)) {
						LcLocale oLocale = new LcLocale(sLocale);
						if (oLocale.isValid()) {
							sLocale = oLocale.getName();
							int i = 0, n = oLocales.size();
							for (; i < n; i++)
								if (oLocales.get(i).equals(sLocale))
									break;
							if (i == n)
								oLocales.add(sLocale);
						}
					}
				}
			}
		}
		//
		// Check the value value on all picture nodes of the template model.
		//
		else if (oNode.isSameClass(XFA.PICTURETAG)) {
			TextNode oPicture = oNode.getText(true, false, false);
			if (oPicture != null) {
				String sPicture = oPicture.getValue();
				StringBuilder sCat = new StringBuilder();
				StringBuilder sLoc = new StringBuilder();
				StringBuilder sMask = new StringBuilder();
				if (PictureFmt.isSubPicture(sPicture, 0, sCat, sLoc, sMask)) {	
					LcLocale oLocale = new LcLocale(sLoc.toString());
					if (oLocale.isValid()) {
						String sLocale = oLocale.getName();
						int i = 0, n = oLocales.size();
						for (; i < n; i++)
							if (oLocales.get(i).equals(sLocale))
								break;
						if (i == n)
							oLocales.add(sLocale);
					}
				}
			}
		}
		//
		// Check the locale attribute on subform and field nodes
		// of the locale set model.
		//
		else if (oNode.isSameClass(XFA.LOCALETAG)) {
			String sLocale = oNode.getName();
			if (! sLocale.equals(gsAmbient)) {
				LcLocale oLocale = new LcLocale(sLocale);
				if (oLocale.isValid()) {
					sLocale = oLocale.getName();
					int i = 0, n = oLocales.size();
					for (; i < n; i++)
						if (oLocales.get(i).equals(sLocale))
							break;
					if (i == n)
						oLocales.add(sLocale);
				}
			}
		}
		//
		// Draw nodes in the template model have no children of interest.
		// Locale nodes in the locale set model have no children of interest.
		// Recurse down all other nodes.
		//
		if (! oNode.isSameClass(XFA.DRAWTAG)
				&& ! oNode.isSameClass(XFA.LOCALETAG)) {
			Node oChild = oNode.getFirstXFAChild();
			while (oChild instanceof Element) {
				find((Element) oChild, oLocales);
				oChild = oChild.getNextXFASibling();
			}
		}
	}

	private LcData.LcRunTimeData walk(Node oNode, StringHolder sLoc, LcData.LcRunTimeData oLcData) {
		if (oNode == null) {
			return oLcData;
		}
		else if (oNode.isSameClass(XFA.LOCALETAG)) {
			String sDesc = ((Element) oNode).getAttribute(XFA.DESCTAG).toString();
			String sName = oNode.getName();
			if (StringUtils.isEmpty(sName))
				return oLcData;
			
			oLcData = LcData.get(sName);
			
			Node oChild = oNode.getFirstXFAChild();
			while (oChild != null) {
				oLcData = walk(oChild, sLoc, oLcData);
				oChild = oChild.getNextXFASibling();
			}
			
			LcLocale oLocale = new LcLocale(sName);
			if (!oLocale.isValid())
				LcLocale.update(sName, sDesc);
			
			sLoc.value = LcLocale.normalize(sName);
		}
		else if (oNode.isSameClass(XFA.CALENDARSYMBOLSTAG)) {
			Node oChild = oNode.getFirstXFAChild();
			while (oChild != null) {
				oLcData = walk(oChild, sLoc, oLcData);
				oChild = oChild.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.MONTHNAMESTAG)) {
			int eAbbr = ((Element) oNode).getEnum(XFA.ABBRTAG);
			switch (eAbbr) {
			case EnumAttr.BOOL_FALSE:
			case EnumAttr.BOOL_TRUE:
				break;
			default:
				return oLcData;
			}
			Element oMonth = (Element) oNode.getFirstXFAChild();
			for (int i = 0; oMonth != null && i < 12; i++) {
				String sMonth = oMonth.getText(false, false, false).getValue();
				if (eAbbr == EnumAttr.BOOL_TRUE) {
					oLcData.abbrMonthNames[i] = sMonth;
				}
				else  {
					oLcData.monthNames[i] = sMonth;
				}
				oMonth = (Element) oMonth.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.DAYNAMESTAG)) {
			int eAbbr = ((Element) oNode).getEnum(XFA.ABBRTAG);
			switch (eAbbr) {
			case EnumAttr.BOOL_FALSE:
			case EnumAttr.BOOL_TRUE:
				break;
			default:
				return oLcData;
			}
			Element oDay = (Element) oNode.getFirstXFAChild();
			for (int i = 0; oDay != null && i < 7; i++) {
				String sDay = oDay.getText(false, false, false).getValue();
				if (eAbbr == EnumAttr.BOOL_TRUE) {
					oLcData.abbrWeekdayNames[i] = sDay;
				}
				else {
					oLcData.dayNames[i] = sDay;
				}
				oDay = (Element) oDay.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.MERIDIEMNAMESTAG)) {
			Element oMeridiem = (Element) oNode.getFirstXFAChild();
			for (int i = 0; oMeridiem != null && i < 2; i++) {
				String sMeridiem = oMeridiem.getText(false, false, false).getValue();
				oLcData.meridiemNames[i] = sMeridiem;
				oMeridiem = (Element) oMeridiem.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.ERANAMESTAG)) {
			Element oEra = (Element) oNode.getFirstXFAChild();
			for (int i = 0; oEra != null && i < 2; i++) {
				String sEra = oEra.getText(false, false, false).getValue();
				oLcData.eraNames[i] = sEra;
				oEra = (Element) oEra.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.DATEPATTERNSTAG)) {
			Element oDatePat = (Element) oNode.getFirstXFAChild();
			while (oDatePat != null) {
				int eName = oDatePat.getEnum(XFA.NAMETAG);
				String sPat = oDatePat.getText(false, false, false).getValue();
				switch (eName) {
				case EnumAttr.PATTERN_FULL:
					oLcData.datePatterns[LcData.FULL] = sPat;
					break;
				case EnumAttr.PATTERN_LONG:
					oLcData.datePatterns[LcData.LONG] = sPat;
					break;
				case EnumAttr.PATTERN_MED:
					oLcData.datePatterns[LcData.MED] = sPat;
					break;
				case EnumAttr.PATTERN_SHORT:
					oLcData.datePatterns[LcData.SHORT] = sPat;
					break;
				default:
					return oLcData;
				}
				oDatePat = (Element) oDatePat.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.TIMEPATTERNSTAG)) {
			Element oTimePat = (Element) oNode.getFirstXFAChild();
			while (oTimePat != null) {
				int eName = oTimePat.getEnum(XFA.NAMETAG);
				String sPat = oTimePat.getText(false, false, false).getValue();
				switch (eName) {
				case EnumAttr.PATTERN_FULL:
					oLcData.timePatterns[LcData.FULL] = sPat;
					break;
				case EnumAttr.PATTERN_LONG:
					oLcData.timePatterns[LcData.LONG] = sPat;
					break;
				case EnumAttr.PATTERN_MED:
					oLcData.timePatterns[LcData.MED] = sPat;
					break;
				case EnumAttr.PATTERN_SHORT:
					oLcData.timePatterns[LcData.SHORT] = sPat;
					break;
				default:
					return oLcData;
				}
				oTimePat = (Element) oTimePat.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.DATETIMESYMBOLSTAG)) {
			Element oDateTimePat = (Element) oNode;
			String sPat = oDateTimePat.getText(false, false, false).getValue();
			oLcData.dateTimeSymbols[0] = sPat;
		}
		else if (oNode.isSameClass(XFA.NUMBERPATTERNSTAG)) {
			Element oNumPat = (Element) oNode.getFirstXFAChild();
			while (oNumPat != null) {
				int eName = oNumPat.getEnum(XFA.NAMETAG);
				String sPat = oNumPat.getText(false, false, false).getValue();
				switch (eName) {
				case EnumAttr.PATTERN_NUMERIC:
					oLcData.numberPatterns[LcData.NUMERIC] = sPat;
					break;
				case EnumAttr.PATTERN_CURRENCY:
					oLcData.numberPatterns[LcData.CURRENCY] = sPat;
					break;
				case EnumAttr.PATTERN_PERCENT:
					oLcData.numberPatterns[LcData.PERCENT] = sPat;
					break;
				default:
					return oLcData;
				}
				oNumPat = (Element) oNumPat.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.NUMBERSYMBOLSTAG)) {
			Element oNumSym = (Element) oNode.getFirstXFAChild();
			while (oNumSym != null) {
				int eName = oNumSym.getEnum(XFA.NAMETAG);
				String sSym = oNumSym.getText(false, false, false).getValue();
				switch (eName) {
				case EnumAttr.NUMERIC_DECIMAL:
					oLcData.numericSymbols[LcData.NUM_DECIMAL] = sSym;
					break;
				case EnumAttr.NUMERIC_GROUPING:
					oLcData.numericSymbols[LcData.NUM_GROUPING] = sSym;
					break;
				case EnumAttr.NUMERIC_PERCENT:
					oLcData.numericSymbols[LcData.NUM_PERCENT] = sSym;
					break;
				case EnumAttr.NUMERIC_MINUS:
					oLcData.numericSymbols[LcData.NUM_MINUS] = sSym;
					break;
				case EnumAttr.NUMERIC_ZERO:
					oLcData.numericSymbols[LcData.NUM_ZERO] = sSym;
					break;
				default:
					return oLcData;
				}
				oNumSym = (Element) oNumSym.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.CURRENCYSYMBOLSTAG)) {
			Element oCurSym = (Element) oNode.getFirstXFAChild();
			while (oCurSym != null) {
				int eName = oCurSym.getEnum(XFA.NAMETAG);
				String sSym = oCurSym.getText(false, false, false).getValue();
				switch (eName) {
				case EnumAttr.CURRENCY_SYMBOL:
					oLcData.currencySymbols[LcData.CUR_SYMBOL] = sSym;
					break;
				case EnumAttr.CURRENCY_ISONAME:
					oLcData.currencySymbols[LcData.CUR_ISONAME] = sSym;
					break;
				case EnumAttr.CURRENCY_DECIMAL:
					oLcData.currencySymbols[LcData.CUR_DECIMAL] = sSym;
					break;
				default:
					return oLcData;
				}
				oCurSym = (Element) oCurSym.getNextXFASibling();
			}
		}
		else if (oNode.isSameClass(XFA.TYPEFACESTAG)) {
			int nTypefaces = oNode.getXMLChildCount();
			//Watson 1442022 - keep typefaces out until a later version
			oLcData.typefaceList.clear();
			for (int i = 0; i < nTypefaces; i++) {
				Element oTypeface = ((Element) oNode).getElement(XFA.TYPEFACETAG, i);
				String sName = oTypeface.getAttribute(XFA.NAMETAG).toString();
				String sCorrectedName = null;

				// Watson# 1680903.  Unfortunately, the incorrect typeface names for 
				// the CJK fonts were written out in several LC 8.0.1 versions of Designer.
				// Since these names were not used until LC 8.2 / Acrobat 9, we didn't
				// notice until Acrobat 9 development.  We need to map these names to the 
				// correct names here (the correct names can be found at the top of 
				// lcdata.cpp).
				if (sName.equals("Kozuka Gothic Pro VI"))
					sCorrectedName = "Kozuka Gothic Pro-VI M";
				else if (sName.equals("Kozuka Mincho Pro VI"))
					sCorrectedName = "Kozuka Mincho Pro-VI R";
				else if (sName.equals("Adobe Ming Std"))
					sCorrectedName = "Adobe Ming Std L";
				else if (sName.equals("Adobe Song Std"))
					sCorrectedName = "Adobe Song Std L";
				else if (sName.equals("Adobe Myungjo Std"))
					sCorrectedName = "Adobe Myungjo Std M";

				if (!StringUtils.isEmpty(sCorrectedName)) {
					sName = sCorrectedName;
					// Update the localeSet packet with the correct value, excpet for the XFA run-time (Acrobat / Reader).  We don't propagate
					// "fix-ups" to XFA packets in the run-time to because it could break security.
					Attribute oProp = new StringAttr(XFA.NAME, sName);
					oTypeface.setAttribute(oProp, XFA.NAMETAG);
				}

				oLcData.typefaceList.add(sName);
			}
			// Entries found above are additive, not exhaustive.
			// The list needs to be augmented with unique entries
			// from the root list.
			LcData oRootData = new LcData("root");
			List oRootList = oRootData.getTypefaces();
			for (int i = 0; i < oRootList.size(); i++) {
				String sName = (String) oRootList.get(i);
				if (! oLcData.typefaceList.contains(sName))
					oLcData.typefaceList.add(sName);
			}
		}
		return oLcData;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy