You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Property.java 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. /*
  2. *
  3. * Copyright 1999-2003 The Apache Software Foundation.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. *
  18. * $Id$
  19. */
  20. package org.apache.fop.fo.properties;
  21. import java.util.Iterator;
  22. import java.util.Map;
  23. import java.util.logging.Logger;
  24. import org.apache.fop.apps.Fop;
  25. import org.apache.fop.datatypes.Auto;
  26. import org.apache.fop.datatypes.CountryType;
  27. import org.apache.fop.datatypes.EnumType;
  28. import org.apache.fop.datatypes.LanguageType;
  29. import org.apache.fop.datatypes.MappedNumeric;
  30. import org.apache.fop.datatypes.NCName;
  31. import org.apache.fop.datatypes.NoType;
  32. import org.apache.fop.datatypes.None;
  33. import org.apache.fop.datatypes.Numeric;
  34. import org.apache.fop.datatypes.PropertyValue;
  35. import org.apache.fop.datatypes.PropertyValueList;
  36. import org.apache.fop.datatypes.ScriptType;
  37. import org.apache.fop.datatypes.indirect.FromNearestSpecified;
  38. import org.apache.fop.datatypes.indirect.FromParent;
  39. import org.apache.fop.datatypes.indirect.Inherit;
  40. import org.apache.fop.datatypes.indirect.InheritedValue;
  41. import org.apache.fop.fo.FONode;
  42. import org.apache.fop.fo.PropNames;
  43. import org.apache.fop.fo.PropertyConsts;
  44. import org.apache.fop.fo.ShorthandPropSets;
  45. import org.apache.fop.fo.expr.PropertyException;
  46. import org.apache.fop.fo.expr.PropertyNotImplementedException;
  47. /**
  48. * Parent class for all of the individual property classes. It also contains
  49. * sets of integer constants for various types of data.
  50. *
  51. * @author <a href="mailto:pbwest@powerup.com.au">Peter B. West</a>
  52. * @version $Revision$ $Name$
  53. */
  54. public class Property {
  55. private static final String tag = "$Name$";
  56. private static final String revision = "$Revision$";
  57. protected static final Logger logger = Logger.getLogger(Fop.fopPackage);
  58. /*
  59. * The list of property data types. These are used to form a bitmap of
  60. * the property data types that are valid for values of each of the
  61. * properties.
  62. *
  63. * Maintain the following list by
  64. * in XEmacs:
  65. * set the region to cover the list, EXCLUDING the final (-ve) value
  66. * M-1 M-| followed by the command
  67. * perl -p -e 'BEGIN{$n=0;$n2=0};$n2=2**$n,$n++ if s/= [0-9]+/= $n2/'
  68. * in vi:
  69. * set a mark (ma) at the end of the list but one.
  70. * Go to the beginning and
  71. * !'aperl -p -e ... etc
  72. *
  73. * N.B. The maximum value that can be handled in this way is
  74. * 2^30 or 1073741824. The -ve value is the equivalent of 2^31.
  75. */
  76. /**
  77. * Constant specifying a property data type or types.
  78. */
  79. public static final int
  80. NOTYPE = 0
  81. ,INTEGER = 1
  82. ,FLOAT = 2
  83. ,LENGTH = 4
  84. ,ANGLE = 8
  85. ,PERCENTAGE = 16
  86. ,CHARACTER_T = 32
  87. ,LITERAL = 64
  88. ,NCNAME = 128
  89. ,COLOR_T = 256
  90. ,COUNTRY_T = 512
  91. ,LANGUAGE_T = 1024
  92. ,SCRIPT_T = 2048
  93. ,URI_SPECIFICATION = 4096
  94. ,TIME = 8192
  95. ,FREQUENCY = 16384
  96. // Pseudotypes
  97. ,BOOL = 32768
  98. ,INHERIT = 65536
  99. ,ENUM = 131072
  100. ,MAPPED_LENGTH = 262144
  101. ,SHORTHAND = 524288
  102. ,COMPLEX = 1048576
  103. ,AUTO = 2097152
  104. ,NONE = 4194304
  105. ,AURAL = 8388608
  106. // Color plus transparent
  107. ,COLOR_TRANS = 16777216
  108. ,MIMETYPE = 33554432
  109. ,FONTSET = 67108864
  110. ,COMPOUND = 134217728
  111. // ,SPARE = 268435456
  112. // ,SPARE = 536870912
  113. // ,SPARE = 1073741824
  114. // ,SPARE = -2147483648
  115. // A number of questions are unresolved about the interaction of
  116. // complex parsing, property expression parsing & property validation.
  117. // At this time (2002/07/03) it looks as though the refineParsing() method
  118. // will take full validation responsibility, so it will not be
  119. // necessary to specify any individual datatypes besides COMPLEX in the
  120. // property dataTypes field. This renders some such specifications
  121. // redundant. On the other hand, if such individual datatype validation
  122. // becomes necessary, the datatype settings for properties with COMPLEX
  123. // will have to be adjusted. pbw
  124. ,NUMBER = FLOAT | INTEGER
  125. ,ENUM_TYPE = ENUM | MAPPED_LENGTH
  126. ,STRING = LITERAL | NCNAME
  127. ,HYPH_TYPE = COUNTRY_T | LANGUAGE_T | SCRIPT_T
  128. ,NAME_TYPE = NCNAME | HYPH_TYPE | ENUM_TYPE
  129. ,STRING_TYPE = STRING | NAME_TYPE
  130. ,ANY_TYPE = ~0
  131. ;
  132. /** Constant specifying an initial data type. */
  133. public static final int
  134. NOTYPE_IT = 0
  135. ,INTEGER_IT = 1
  136. ,NUMBER_IT = 2
  137. ,LENGTH_IT = 4
  138. ,ANGLE_IT = 8
  139. ,PERCENTAGE_IT = 16
  140. ,CHARACTER_IT = 32
  141. ,LITERAL_IT = 64
  142. ,NCNAME_IT = 128
  143. ,COLOR_IT = 256
  144. ,COUNTRY_IT = 512
  145. ,URI_SPECIFICATION_IT = 1024
  146. ,BOOL_IT = 2048
  147. ,ENUM_IT = 4096
  148. ,AUTO_IT = 8192
  149. ,NONE_IT = 16384
  150. ,AURAL_IT = 32768
  151. ,TEXT_DECORATION_IT = 65536
  152. // Unused ,FONTSET_IT = 131072
  153. ;
  154. /**
  155. * Bitmap set of initial data types for which getInitialType() must be
  156. * overriden.
  157. */
  158. public static final int
  159. USE_GET_IT_FUNCTION = //NOTYPE_IT performed in Property
  160. INTEGER_IT
  161. | NUMBER_IT
  162. | LENGTH_IT
  163. | ANGLE_IT
  164. | PERCENTAGE_IT
  165. | CHARACTER_IT
  166. | LITERAL_IT
  167. | NCNAME_IT
  168. | COLOR_IT
  169. | COUNTRY_IT
  170. | URI_SPECIFICATION_IT
  171. | BOOL_IT
  172. | ENUM_IT
  173. //AUTO_IT performed in Property
  174. //NONE_IT performed in Property
  175. //AURAL_IT performed in Property
  176. | TEXT_DECORATION_IT
  177. ;
  178. /** Constant specifying mapping of property to trait. */
  179. public static final int
  180. NO_TRAIT = 0
  181. ,RENDERING = 1
  182. ,DISAPPEARS = 2
  183. ,SHORTHAND_MAP = 4
  184. ,REFINE = 8
  185. ,FORMATTING = 16
  186. ,SPECIFICATION = 32
  187. ,NEW_TRAIT = 64
  188. ,FONT_SELECTION = 128
  189. ,VALUE_CHANGE = 256
  190. ,REFERENCE = 512
  191. ,ACTION = 1024
  192. ,MAGIC = 2048
  193. ;
  194. /*
  195. * Constant specifying inheritance type. Special cases (only line-height
  196. * specified as a &lt;number&gt;, so far) must be handled close to the
  197. * usage point of the property. For line-height, the number is retained
  198. * as the specified and as the computed property value. Because the
  199. * current font-size will always be present in the property set for any
  200. * FONode which requires line-height, the actual length value of the
  201. * line-height can always be calculated at the point of application.
  202. */
  203. /** Constant specifying inheritance type. */
  204. public static final int
  205. NO = 0
  206. ,COMPUTED = 1
  207. ;
  208. public static final int dataTypes = NOTYPE;
  209. public int getDataTypes() {
  210. return dataTypes;
  211. }
  212. public static final int initialValueType = NOTYPE_IT;
  213. public int getInitialValueType() {
  214. return initialValueType;
  215. }
  216. public static final int inherited = NO;
  217. public int getInherited() {
  218. return inherited;
  219. }
  220. private static final int traitMapping = NO_TRAIT;
  221. public int getTraitMapping() {
  222. return traitMapping;
  223. }
  224. public static Map enumHash = null;
  225. /**
  226. * Is this a corresponding absolute property?
  227. * Such properties must override this method.
  228. * @return answer
  229. */
  230. public boolean isCorrespondingAbsolute() {
  231. return false;
  232. }
  233. /**
  234. * Is this a corresponding relative property?
  235. * Such properties must override this method.
  236. * @return answer
  237. */
  238. public boolean isCorrespondingRelative() {
  239. return false;
  240. }
  241. public Property() {}
  242. /**
  243. * Form a string representation of bitmap of datatypes.
  244. * @param datatypes - a bitmap of datatype(s).
  245. * @return <tt>String</tt> containing a list of text names of datatypes
  246. * found in the bitmap. Individual names are enclosed in angle brackets
  247. * and separated by a vertical bar. Psuedo-datatypes are in upper case.
  248. * @exception PropertyException if no matches are found.
  249. */
  250. public static String listDataTypes(int datatypes)
  251. throws PropertyException
  252. {
  253. String typeNames = "";
  254. if ((datatypes & ANY_TYPE) == ANY_TYPE) return "<ALL-TYPES>";
  255. if ((datatypes & INTEGER) != 0) typeNames += "<integer>|";
  256. if ((datatypes & NUMBER) != 0) typeNames += "<number>|";
  257. if ((datatypes & LENGTH) != 0) typeNames += "<length>|";
  258. if ((datatypes & ANGLE) != 0) typeNames += "<angle>|";
  259. if ((datatypes & PERCENTAGE) != 0) typeNames += "<percentage>|";
  260. if ((datatypes & CHARACTER_T) != 0) typeNames += "<character>|";
  261. if ((datatypes & STRING) != 0) typeNames += "<string>|";
  262. if ((datatypes & NCNAME) != 0) typeNames += "<ncname>|";
  263. if ((datatypes & COLOR_T) != 0) typeNames += "<color>|";
  264. if ((datatypes & COUNTRY_T) != 0) typeNames += "<country>|";
  265. if ((datatypes & LANGUAGE_T) != 0) typeNames += "<language>|";
  266. if ((datatypes & SCRIPT_T) != 0) typeNames += "<script>|";
  267. if ((datatypes & URI_SPECIFICATION) != 0) typeNames
  268. += "<uri-specification>|";
  269. if ((datatypes & TIME) != 0) typeNames += "<time>|";
  270. if ((datatypes & FREQUENCY) != 0) typeNames += "<frequency>|";
  271. if ((datatypes & BOOL) != 0) typeNames += "<BOOL>|";
  272. if ((datatypes & INHERIT) != 0) typeNames += "<INHERIT>|";
  273. if ((datatypes & ENUM) != 0) typeNames += "<ENUM>|";
  274. if ((datatypes & MAPPED_LENGTH) != 0) typeNames
  275. += "<MAPPED_LENGTH>|";
  276. if ((datatypes & SHORTHAND) != 0) typeNames += "<SHORTHAND>|";
  277. if ((datatypes & COMPLEX) != 0) typeNames += "<COMPLEX>|";
  278. if ((datatypes & AUTO) != 0) typeNames += "<AUTO>|";
  279. if ((datatypes & NONE) != 0) typeNames += "<NONE>|";
  280. if ((datatypes & AURAL) != 0) typeNames += "<AURAL>|";
  281. if ((datatypes & COLOR_TRANS) != 0) typeNames += "<COLOR_TRANS>|";
  282. if ((datatypes & MIMETYPE) != 0) typeNames += "<MIMETYPE>|";
  283. if ((datatypes & FONTSET) != 0) typeNames += "<FONTSET>|";
  284. if (typeNames == "") throw new PropertyException
  285. ("No valid data type in " + datatypes);
  286. return typeNames.substring(0, typeNames.length() - 1);
  287. }
  288. /**
  289. * Derive inherited value for the given property.
  290. * This method must be overriden by properties with special requirements.
  291. * @param foTree the <tt>FOTree</tt> being built
  292. * @param property the <tt>int</tt> property index
  293. * @return <tt>PropertyValue</tt> the inherited property value for the
  294. * property. It contains the inherited <i>computed</i> value, and no
  295. * <i>specified</i> value.
  296. * @exception <tt>PropertyException</tt>
  297. */
  298. /*
  299. public static PropertyValue inheritance(FOTree foTree, int property)
  300. throws PropertyException
  301. {
  302. // Is it inherited? This question is not asked here. Should it be
  303. // determined in here or outside?
  304. return foTree.getCurrentInherited(property);
  305. }
  306. */
  307. /** Constant for nested <tt>refineParsing</tt> methods. */
  308. public static boolean IS_NESTED = true;
  309. /** Constant for non-nested <tt>refineParsing</tt> methods. */
  310. public static boolean NOT_NESTED = false;
  311. /**
  312. * The final stage of property expression parsing.
  313. * <ol>
  314. * <li>PropertyTokenizer</li>
  315. * <li>PropertyParser - returns context-free <tt>PropertyValue</tt>s
  316. * recognizable by the parser</li>
  317. * <li>refineParsing - verifies results from parser, translates
  318. * property types like NCName into more specific value types,
  319. * resolves enumeration types, etc.</li>
  320. * </ol>
  321. *
  322. * <p>This method is overriden by individual property classes which
  323. * require specific processing.
  324. * @param propindex - the <tt>int</tt> property index.
  325. * @param foNode - the <tt>FONode</tt> being built
  326. * @param value - <tt>PropertyValue</tt> returned by the parser
  327. */
  328. public PropertyValue refineParsing
  329. (int propindex, FONode foNode, PropertyValue value)
  330. throws PropertyException
  331. {
  332. return refineParsing(propindex, foNode, value, NOT_NESTED);
  333. }
  334. /**
  335. * Do the work for the three argument refineParsing method.
  336. * @param propindex - the <tt>int</tt> property index.
  337. * @param foNode - the <tt>FONode</tt> being built
  338. * @param value - <tt>PropertyValue</tt> returned by the parser
  339. * @param nested - <tt>boolean</tt> indicating whether this method is
  340. * called normally (false), or as part of another <i>refineParsing</i>
  341. * method.
  342. * @see #refineParsing(int,FONode,PropertyValue)
  343. */
  344. public PropertyValue refineParsing(int propindex,
  345. FONode foNode, PropertyValue value, boolean nested)
  346. throws PropertyException
  347. {
  348. //int propindex = value.getProperty();
  349. if (propindex != value.getProperty()) // DEBUG
  350. throw new PropertyException
  351. ("Mismatched property and value.property.");
  352. String propName = PropNames.getPropertyName(propindex);
  353. int proptype = value.getType();
  354. int dataTypes = PropertyConsts.pconsts.getDataTypes(propindex);
  355. PropertyValue pv;
  356. if ((dataTypes & AURAL) != 0)
  357. throw new PropertyNotImplementedException
  358. ("AURAL properties are not supported");
  359. switch (proptype) {
  360. case PropertyValue.NUMERIC:
  361. // Can be any of
  362. // INTEGER, FLOAT, LENGTH, PERCENTAGE, ANGLE, FREQUENCY or TIME
  363. if ((dataTypes & (INTEGER | FLOAT | LENGTH | PERCENTAGE
  364. | ANGLE | FREQUENCY | TIME)) != 0)
  365. return value;
  366. throw new PropertyException
  367. ("Numeric value invalid for " + propName);
  368. case PropertyValue.INTEGER:
  369. if ((dataTypes & NUMBER) != 0)
  370. return value;
  371. throw new PropertyException
  372. ("IntegerType value invalid for " + propName);
  373. case PropertyValue.NCNAME:
  374. String ncname = ((NCName)value).getNCName();
  375. // Can by any of
  376. // NCNAME, COUNTRY_T, LANGUAGE_T, SCRIPT_T, ENUM
  377. // MAPPED_LENGTH or CHARACTER_T
  378. if ((dataTypes & (NCNAME | CHARACTER_T)) != 0)
  379. return value;
  380. if ((dataTypes & COUNTRY_T) != 0)
  381. return new CountryType(propindex, ncname);
  382. if ((dataTypes & LANGUAGE_T) != 0)
  383. return new LanguageType(propindex, ncname);
  384. if ((dataTypes & SCRIPT_T) != 0)
  385. return new ScriptType(propindex, ncname);
  386. if ((dataTypes & ENUM) != 0)
  387. return new EnumType(propindex, ncname);
  388. if ((dataTypes & MAPPED_LENGTH) != 0)
  389. return (new MappedNumeric
  390. (foNode, propindex, ncname)).getMappedNumValue();
  391. throw new PropertyException
  392. ("NCName value invalid for " + propName);
  393. case PropertyValue.ENUM:
  394. if ((dataTypes & ENUM) != 0) return value;
  395. throw new PropertyException
  396. ( "Enumerated value invalid for " + propName);
  397. case PropertyValue.LITERAL:
  398. // Can be LITERAL or CHARACTER_T
  399. if ((dataTypes & (LITERAL | CHARACTER_T)) != 0) return value;
  400. throw new PropertyException
  401. ("Literal value invalid for " + propName);
  402. case PropertyValue.AUTO:
  403. if ((dataTypes & AUTO) != 0) return value;
  404. throw new PropertyException("'auto' invalid for " + propName);
  405. case PropertyValue.BOOL:
  406. if ((dataTypes & BOOL) != 0) return value;
  407. throw new PropertyException
  408. ("Boolean value invalid for " + propName);
  409. case PropertyValue.COLOR_TYPE:
  410. // Can be COLOR_T or COLOR_TRANS
  411. if ((dataTypes & (COLOR_T | COLOR_TRANS)) != 0) return value;
  412. throw new PropertyException("'none' invalid for " + propName);
  413. case PropertyValue.NONE:
  414. // Some instances of 'none' are part of an enumeration, but
  415. // the parser will find and return 'none' as a None
  416. // PropertyValue.
  417. // In these cases, the individual property's refineParsing
  418. // method must override this method.
  419. if ((dataTypes & NONE) != 0) return value;
  420. throw new PropertyException("'none' invalid for " + propName);
  421. case PropertyValue.URI_TYPE:
  422. if ((dataTypes & URI_SPECIFICATION) != 0) return value;
  423. throw new PropertyException("uri invalid for " + propName);
  424. case PropertyValue.MIME_TYPE:
  425. if ((dataTypes & MIMETYPE) != 0) return value;
  426. throw new PropertyException
  427. ("mimetype invalid for " + propName);
  428. // The following types cannot have their values validated in advance.
  429. // The result must be validated from within the property type.
  430. case PropertyValue.FROM_PARENT:
  431. pv = ((FromParent)value).resolve(foNode);
  432. if (pv == value) return value; // unable to resolve
  433. // TODO: validate here
  434. return pv;
  435. case PropertyValue.FROM_NEAREST_SPECIFIED:
  436. pv = ((FromNearestSpecified)value).resolve(foNode);
  437. if (pv == value) return value; // unable to resolve
  438. // TODO: validate here
  439. return pv;
  440. case PropertyValue.INHERITED_VALUE:
  441. pv = ((InheritedValue)value).resolve(foNode);
  442. if (pv == value) return value; // unable to resolve
  443. // TODO: validate here
  444. return pv;
  445. case PropertyValue.LIST:
  446. throw new PropertyException
  447. ("PropertyValueList passed to Property.refineParsing for "
  448. + propName + "\n" + value.toString());
  449. default:
  450. // The COMPOUND test was orginally protected by the
  451. // if ( ! nested) fence. Only within Font, Border and
  452. // Background shorthands is refineParsing called with a
  453. // nested value of 'true'. This may cause problems, in which case
  454. // the COMPOUND processing will have to be repeated within the
  455. // (property instanceof CorrespondingProperty) case.
  456. if ((dataTypes & COMPOUND) != 0)
  457. return ShorthandPropSets.expandCompoundProperty
  458. (foNode.getFOTree(), value);
  459. if ( ! nested) {
  460. int correspIndex = 0;
  461. Property property =
  462. PropertyConsts.pconsts.getProperty(propindex);
  463. if (property instanceof CorrespondingProperty) {
  464. correspIndex =
  465. ((CorrespondingProperty)property)
  466. .getCorrespondingProperty(foNode);
  467. // Note - can't call refineParsing recursively to resolve
  468. // corresponding compounds, because the compound is itself
  469. // a corresponding property
  470. // Create a list, containing this PropertyValue on
  471. // the original property, plus the value on the
  472. // expansion of the corresponding property
  473. PropertyValueList newlist =
  474. new PropertyValueList(propindex);
  475. newlist.add(value);
  476. PropertyValue corresPv = null;
  477. try {
  478. corresPv = (PropertyValue)(value.clone());
  479. } catch (CloneNotSupportedException e) {
  480. throw new PropertyException(e.getMessage());
  481. }
  482. corresPv.setProperty(correspIndex);
  483. corresPv = PropertyConsts.pconsts.refineParsing(
  484. corresPv.getProperty(), foNode,
  485. corresPv, IS_NESTED);
  486. // if it's a list, recursively refine. This will return a list
  487. if (corresPv.getType() == PropertyValue.LIST) {
  488. PropertyValueList pvl =
  489. refineExpansionList(
  490. corresPv.getProperty(), foNode,
  491. (PropertyValueList)corresPv);
  492. newlist.addAll(pvl);
  493. } else { // single element
  494. newlist.add(corresPv);
  495. }
  496. return newlist;
  497. }
  498. if (proptype == PropertyValue.INHERIT) {
  499. if ((dataTypes & INHERIT) != 0)
  500. return ((Inherit)value).resolve(foNode);
  501. throw new PropertyException
  502. ("'inherit' invalid for " + propName);
  503. }
  504. }
  505. throw new PropertyException
  506. ("Inappropriate dataTypes passed to Property.refineParsing: "
  507. + value.getClass().getName());
  508. }
  509. }
  510. /**
  511. * Refine a list of property values against their properties.
  512. * Expansion lists are generated by shorthand and compound expansion.
  513. * The set of properties will, in general, be different from the
  514. * generating property, which will be the one associated with the list
  515. * itself.
  516. * @param propindex - the <tt>int</tt> property index.
  517. * @param foNode - the <tt>FONode</tt> for which the properties are
  518. * being processed.
  519. * @param list - the list of <tt>PropertyValues</tt> to be refined.
  520. * @return a <tt>PropertyValueList>/tt> containing the refined property
  521. * values.
  522. */
  523. public PropertyValueList refineExpansionList
  524. (int propindex, FONode foNode, PropertyValueList list)
  525. throws PropertyException
  526. {
  527. if (propindex != list.getProperty()) // DEBUG
  528. throw new PropertyException
  529. ("Mismatch between propindex and list property.");
  530. PropertyValueList newlist = new PropertyValueList(list.getProperty());
  531. Iterator properties = list.iterator();
  532. while (properties.hasNext()) {
  533. // refine the next element
  534. PropertyValue pv = (PropertyValue)(properties.next());
  535. pv = PropertyConsts.pconsts.refineParsing
  536. (pv.getProperty(), foNode, pv);
  537. // if it's a list, recursively refine. This will return a list
  538. if (pv.getType() == PropertyValue.LIST) {
  539. PropertyValueList pvl = refineExpansionList
  540. (pv.getProperty(), foNode, (PropertyValueList)pv);
  541. newlist.addAll(pvl);
  542. } else { // single element
  543. newlist.add(pv);
  544. }
  545. }
  546. return newlist;
  547. }
  548. /**
  549. * Determine whether argument <i>list</i> contains a space-separated list
  550. * from the parser.
  551. * A space-separated list will be represented by a
  552. * <tt>PropertyValueList</tt> as the only element of the argument
  553. * <tt>PropertyValueList</tt>.
  554. * @param list - the containing list.
  555. * @return the contained space-separated list.
  556. * @throws PropertyException if <i>list</i> contains more than
  557. * one element or if the contained element is not a list.
  558. */
  559. protected PropertyValueList spaceSeparatedList (PropertyValueList list)
  560. throws PropertyException
  561. {
  562. if (list.size() != 1)
  563. throw new PropertyException
  564. (list.getClass().getName() + " list is not a "
  565. + "single list of space-separated values");
  566. PropertyValue val2 = (PropertyValue)(list.getFirst());
  567. if ( ! (val2.getType() == PropertyValue.LIST))
  568. throw new PropertyException
  569. (list.getClass().getName() + " list is not a "
  570. + "single list of space-separated values");
  571. return (PropertyValueList)val2;
  572. }
  573. /**
  574. * Return the EnumType derived from the argument.
  575. * The argument must be an NCName whose string value is a
  576. * valid Enum for the property associated with the NCName.
  577. * @param value <tt>PropertyValue</tt>
  578. * @param property <tt>int</tt> the target property index
  579. * @param type <tt>String</tt> type of expected enumval - for
  580. * exception messages only
  581. * @return <tt>EnumValue</tt> equivalent of the argument
  582. * @exception PropertyException
  583. */
  584. protected EnumType getEnum(PropertyValue value,
  585. int property, String type)
  586. throws PropertyException
  587. {
  588. if (value.getType() != PropertyValue.NCNAME)
  589. throw new PropertyException
  590. (value.getClass().getName()
  591. + " instead of " + type + " for "
  592. + PropNames.getPropertyName(property));
  593. NCName ncname = (NCName)value;
  594. try {
  595. return new EnumType(property, ncname.getNCName());
  596. } catch (PropertyException e) {
  597. throw new PropertyException
  598. (ncname.getNCName()
  599. + " instead of " + type + " for "
  600. + PropNames.getPropertyName(property));
  601. }
  602. }
  603. /**
  604. * Get the <tt>int</tt> index corresponding to an enumeration keyword
  605. * for this property.
  606. * @param enumval - a <tt>String</tt> containing the enumeration text.
  607. * @return <tt>int</tt> constant representing the enumeration value.
  608. * @exception PropertyException
  609. */
  610. public int getEnumIndex(String enumval)
  611. throws PropertyException
  612. {
  613. throw new PropertyException("ENUM not supported.");
  614. }
  615. /**
  616. * @param enumIndex <tt>int</tt> containing the enumeration index.
  617. * @return <tt>String</tt> containing the enumeration text.
  618. * @exception PropertyException
  619. */
  620. public String getEnumText(int enumIndex)
  621. throws PropertyException
  622. {
  623. throw new PropertyException("ENUM not supported.");
  624. }
  625. /**
  626. * Map the String value of an enumval to its integer equivalent.
  627. * @param value the enumval text
  628. * @param values an <tt>ROStringArray</tt> of all of the enumval text values.
  629. * This array is effectively 1-based.
  630. * @return the integer equivalent of the enumval text
  631. * @exception PropertyException if the enumval text is not valid.
  632. */
  633. public int enumValueToIndex(String value, String[] values)
  634. throws PropertyException
  635. {
  636. for (int i = 1; i < values.length; i++) {
  637. if (value.equals(values[i])) {
  638. return i;
  639. }
  640. }
  641. throw new PropertyException("Enum text " + value +" not found.");
  642. }
  643. /**
  644. * Convert an enumeration index value to a length. This is the
  645. * fallback implementation of this function for properties which do not
  646. * support a MAPPED_LENGTH type. Those which do must override this
  647. * method.
  648. * @param enumval - the enumeration index.
  649. * @return a <tt>Numeric</tt>. This implementation never returns.
  650. * @throws PropertyException
  651. */
  652. public Numeric getMappedLength(FONode node, int enumval)
  653. throws PropertyException
  654. {
  655. throw new PropertyException
  656. ("MAPPED_LENGTH not supported.");
  657. }
  658. /**
  659. * Fallback getInitialValue function. This function only handles
  660. * those initial value types NOT in the set USE_GET_IT_FUNCTION. It
  661. * should be overriden by all properties whose initial values come from
  662. * that set.
  663. * @param property <tt>int</tt> property index
  664. * @return <tt>PropertyValue</tt>
  665. * @exception PropertyException
  666. * @exception PropertyNotImplementedException
  667. */
  668. public PropertyValue getInitialValue(int property)
  669. throws PropertyException
  670. {
  671. int initialValueType =
  672. PropertyConsts.pconsts.getInitialValueType(property);
  673. logger.fine("In Property getInitialValue property " + property);
  674. if ((initialValueType & Property.USE_GET_IT_FUNCTION) != 0)
  675. throw new PropertyException
  676. ("Property.getInitialValue() called for property with "
  677. + "initial value type in USE_GET_IT_FUNCTION : "
  678. + property + " "
  679. + PropNames.getPropertyName(property));
  680. switch (initialValueType) {
  681. case NOTYPE_IT:
  682. return new NoType(property);
  683. case AUTO_IT:
  684. return new Auto(property);
  685. case NONE_IT:
  686. return new None(property);
  687. case AURAL_IT:
  688. // TODO Arrange to ignore and log PropertyNotImplemented
  689. throw new PropertyNotImplementedException
  690. ("Aural properties not implemented: "
  691. + PropNames.getPropertyName(property));
  692. default:
  693. throw new PropertyException
  694. ("Unexpected initial value type " + initialValueType
  695. + " for " + PropNames.getPropertyName(property));
  696. }
  697. }
  698. }