PageRenderTime 163ms CodeModel.GetById 25ms RepoModel.GetById 7ms app.codeStats 0ms

/document/fr.opensagres.xdocreport.document.docx/src/main/java/fr/opensagres/xdocreport/document/docx/preprocessor/sax/MergefieldBufferedRegion.java

https://code.google.com/
Java | 209 lines | 129 code | 22 blank | 58 comment | 22 complexity | 4689419cf78cd9890e8205e278ed65d6 MD5 | raw file
  1. /**
  2. * Copyright (C) 2011 Angelo Zerr <angelo.zerr@gmail.com> and Pascal Leclercq <pascal.leclercq@gmail.com>
  3. *
  4. * All rights reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. package fr.opensagres.xdocreport.document.docx.preprocessor.sax;
  26. import org.xml.sax.Attributes;
  27. import fr.opensagres.xdocreport.core.document.DocumentKind;
  28. import fr.opensagres.xdocreport.core.utils.StringUtils;
  29. import fr.opensagres.xdocreport.document.preprocessor.sax.BufferedElement;
  30. import fr.opensagres.xdocreport.document.preprocessor.sax.TransformedBufferedDocumentContentHandler;
  31. import fr.opensagres.xdocreport.document.textstyling.ITransformResult;
  32. import fr.opensagres.xdocreport.template.formatter.Directive;
  33. import fr.opensagres.xdocreport.template.formatter.FieldMetadata;
  34. import fr.opensagres.xdocreport.template.formatter.IDocumentFormatter;
  35. public abstract class MergefieldBufferedRegion
  36. extends BufferedElement
  37. {
  38. private static final String W_P = "w:p";
  39. private static final String MERGEFORMAT = "\\* MERGEFORMAT";
  40. private static final String MERGEFIELD_FIELD_TYPE = "MERGEFIELD";
  41. private static final String HYPERLINK_FIELD_TYPE = "HYPERLINK";
  42. private final TransformedBufferedDocumentContentHandler handler;
  43. private String fieldName;
  44. private BufferedElement tRegion;
  45. public MergefieldBufferedRegion( TransformedBufferedDocumentContentHandler handler, BufferedElement parent,
  46. String uri, String localName, String name, Attributes attributes )
  47. {
  48. super( parent, uri, localName, name, attributes );
  49. this.handler = handler;
  50. }
  51. public String getFieldName()
  52. {
  53. return fieldName;
  54. }
  55. public String setInstrText( String instrText, FieldMetadata fieldAsTextStyling )
  56. {
  57. // compute field name if it's MERGEFIELD
  58. this.fieldName = getFieldName( this, instrText, fieldAsTextStyling, handler.getFormatter(), handler );
  59. if ( fieldName == null )
  60. {
  61. // Not a MERGEFIELD, instrText must be decoded if it's an HYPERLINK
  62. // and field is an interpolation
  63. // ex : HYPERLINK "mailto:$%7bdeveloper.mail%7d"
  64. // must be modified to
  65. // ex : HYPERLINK "mailto:${developer.mail}"
  66. return decodeInstrTextIfNeeded( instrText );
  67. }
  68. return instrText;
  69. }
  70. private String decodeInstrTextIfNeeded( String instrText )
  71. {
  72. // It's not a mergefield.
  73. IDocumentFormatter formatter = handler.getFormatter();
  74. if ( formatter == null )
  75. {
  76. return instrText;
  77. }
  78. // Test if it's HYPERLINK
  79. // ex : HYPERLINK "mailto:$%7bdeveloper.mail%7d"
  80. int index = instrText.indexOf( HYPERLINK_FIELD_TYPE );
  81. if ( index != -1 )
  82. {
  83. // It's HYPERLINK, remove HYPERLINK prefix
  84. // ex : "mailto:$%7bdeveloper.mail%7d"
  85. String fieldName = instrText.substring( index + HYPERLINK_FIELD_TYPE.length(), instrText.length() ).trim();
  86. if ( StringUtils.isNotEmpty( fieldName ) )
  87. {
  88. // remove double quote
  89. // ex : mailto:$%7bdeveloper.mail%7d
  90. if ( fieldName.startsWith( "\"" ) && fieldName.endsWith( "\"" ) )
  91. {
  92. fieldName = fieldName.substring( 1, fieldName.length() - 1 );
  93. }
  94. // decode it
  95. // ex : mailto:${developer.mail}
  96. fieldName = StringUtils.decode( fieldName );
  97. if ( formatter.containsInterpolation( fieldName ) )
  98. {
  99. // It's an interpolation, returns the decoded field
  100. return StringUtils.decode( instrText );
  101. }
  102. }
  103. }
  104. return instrText;
  105. }
  106. private static String getFieldName( MergefieldBufferedRegion mergefield, String instrText,
  107. FieldMetadata fieldAsTextStyling, IDocumentFormatter formatter,
  108. TransformedBufferedDocumentContentHandler handler )
  109. {
  110. if ( StringUtils.isEmpty( instrText ) )
  111. {
  112. return null;
  113. }
  114. int index = instrText.indexOf( MERGEFIELD_FIELD_TYPE );
  115. if ( index != -1 )
  116. {
  117. // Extract field name and add it to the current buffer
  118. String fieldName = instrText.substring( index + MERGEFIELD_FIELD_TYPE.length(), instrText.length() ).trim();
  119. if ( StringUtils.isNotEmpty( fieldName ) )
  120. {
  121. // Test if fieldName ends with \* MERGEFORMAT
  122. if ( fieldName.endsWith( MERGEFORMAT ) )
  123. {
  124. fieldName = fieldName.substring( 0, fieldName.length() - MERGEFORMAT.length() ).trim();
  125. }
  126. if ( StringUtils.isNotEmpty( fieldName ) )
  127. {
  128. // if #foreach is used w:fldSimple looks like this :
  129. // <w:fldSimple w:instr="MERGEFIELD "#foreach($developer in
  130. // $developers)" \\* MERGEFORMAT\"> to have
  131. // foreach($developer in $developers)
  132. // remove first " if needed
  133. if ( fieldName.startsWith( "\"" ) && fieldName.endsWith( "\"" ) )
  134. {
  135. fieldName = fieldName.substring( 1, fieldName.length() - 1 );
  136. }
  137. // Fix bug
  138. // http://code.google.com/p/xdocreport/issues/detail?id=29
  139. // Replace \" with "
  140. // ex : replace [#if \"a\" = \"one\"]1[#else]not 1[/#if]
  141. // to have [#if "a" = "one"]1[#else]not 1[/#if]
  142. fieldName = StringUtils.replaceAll( fieldName, "\\\"", "\"" );
  143. // ex : remplace [#if &apos;a&apos; = \"one\"]1[#else]not
  144. // 1[/#if]
  145. // to have [#if 'a' = "one"]1[#else]not 1[/#if]
  146. fieldName = StringUtils.xmlUnescape( fieldName );
  147. if ( fieldAsTextStyling != null )
  148. {
  149. // register parent buffered element
  150. long variableIndex = handler.getVariableIndex();
  151. // Find parent paragraph
  152. BufferedElement parent = mergefield.findParent( W_P );
  153. String elementId = handler.registerBufferedElement( variableIndex, parent );
  154. // Set
  155. String setVariableDirective =
  156. formatter.formatAsCallTextStyling( variableIndex, fieldName, DocumentKind.DOCX.name(),
  157. fieldAsTextStyling.getSyntaxKind(),
  158. fieldAsTextStyling.isSyntaxWithDirective(), elementId,
  159. handler.getEntryName() );
  160. String textBefore =
  161. formatter.formatAsTextStylingField( variableIndex, ITransformResult.TEXT_BEFORE_PROPERTY );
  162. String textBody =
  163. formatter.formatAsTextStylingField( variableIndex, ITransformResult.TEXT_BODY_PROPERTY );
  164. String textEnd =
  165. formatter.formatAsTextStylingField( variableIndex, ITransformResult.TEXT_END_PROPERTY );
  166. parent.setContentBeforeStartTagElement( Directive.formatDirective( setVariableDirective + " "
  167. + textBefore, handler.getStartNoParse(), handler.getEndNoParse() ) );
  168. parent.setContentAfterEndTagElement( Directive.formatDirective( textEnd,
  169. handler.getStartNoParse(),
  170. handler.getEndNoParse() ) );
  171. return Directive.formatDirective( textBody, handler.getStartNoParse(), handler.getEndNoParse() );
  172. }
  173. return Directive.formatDirective( fieldName, handler.getStartNoParse(), handler.getEndNoParse() );
  174. }
  175. }
  176. }
  177. return null;
  178. }
  179. public BufferedElement getTRegion()
  180. {
  181. if ( tRegion == null )
  182. {
  183. tRegion = super.findFirstChild( "w:t" );
  184. }
  185. return tRegion;
  186. }
  187. }