PageRenderTime 319ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/src/org/apache/poi/ddf/DefaultEscherRecordFactory.java

https://github.com/minstrelsy/SimpleAndroidDocView
Java | 160 lines | 99 code | 12 blank | 49 comment | 23 complexity | 3324931c58f18c045e9c34e4e1ad839e MD5 | raw file
Possible License(s): Apache-2.0
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.ddf;
  16. import java.lang.reflect.Constructor;
  17. import java.util.HashMap;
  18. import java.util.Map;
  19. import org.apache.poi.util.LittleEndian;
  20. /**
  21. * Generates escher records when provided the byte array containing those records.
  22. *
  23. * @author Glen Stampoultzis
  24. * @author Nick Burch (nick at torchbox . com)
  25. *
  26. * @see EscherRecordFactory
  27. */
  28. public class DefaultEscherRecordFactory implements EscherRecordFactory {
  29. private static Class<?>[] escherRecordClasses = { EscherBSERecord.class,
  30. EscherOptRecord.class, EscherTertiaryOptRecord.class,
  31. EscherClientAnchorRecord.class, EscherDgRecord.class,
  32. EscherSpgrRecord.class, EscherSpRecord.class,
  33. EscherClientDataRecord.class, EscherDggRecord.class,
  34. EscherSplitMenuColorsRecord.class, EscherChildAnchorRecord.class,
  35. EscherTextboxRecord.class };
  36. private static Map<Short, Constructor<? extends EscherRecord>> recordsMap = recordsToMap( escherRecordClasses );
  37. /**
  38. * Creates an instance of the escher record factory
  39. */
  40. public DefaultEscherRecordFactory() {
  41. // no instance initialisation
  42. }
  43. /**
  44. * Generates an escher record including the any children contained under that record.
  45. * An exception is thrown if the record could not be generated.
  46. *
  47. * @param data The byte array containing the records
  48. * @param offset The starting offset into the byte array
  49. * @return The generated escher record
  50. */
  51. public EscherRecord createRecord(byte[] data, int offset) {
  52. short options = LittleEndian.getShort( data, offset );
  53. short recordId = LittleEndian.getShort( data, offset + 2 );
  54. // int remainingBytes = LittleEndian.getInt( data, offset + 4 );
  55. // Options of 0x000F means container record
  56. // However, EscherTextboxRecord are containers of records for the
  57. // host application, not of other Escher records, so treat them
  58. // differently
  59. if (isContainer(options, recordId)) {
  60. EscherContainerRecord r = new EscherContainerRecord();
  61. r.setRecordId( recordId );
  62. r.setOptions( options );
  63. return r;
  64. }
  65. if (recordId >= EscherBlipRecord.RECORD_ID_START
  66. && recordId <= EscherBlipRecord.RECORD_ID_END) {
  67. EscherBlipRecord r;
  68. if (recordId == EscherBitmapBlip.RECORD_ID_DIB ||
  69. recordId == EscherBitmapBlip.RECORD_ID_JPEG ||
  70. recordId == EscherBitmapBlip.RECORD_ID_PNG)
  71. {
  72. r = new EscherBitmapBlip();
  73. }
  74. else if (recordId == EscherMetafileBlip.RECORD_ID_EMF ||
  75. recordId == EscherMetafileBlip.RECORD_ID_WMF ||
  76. recordId == EscherMetafileBlip.RECORD_ID_PICT)
  77. {
  78. r = new EscherMetafileBlip();
  79. } else {
  80. r = new EscherBlipRecord();
  81. }
  82. r.setRecordId( recordId );
  83. r.setOptions( options );
  84. return r;
  85. }
  86. Constructor<? extends EscherRecord> recordConstructor = recordsMap.get(Short.valueOf(recordId));
  87. EscherRecord escherRecord = null;
  88. if (recordConstructor == null) {
  89. return new UnknownEscherRecord();
  90. }
  91. try {
  92. escherRecord = recordConstructor.newInstance(new Object[] {});
  93. } catch (Exception e) {
  94. return new UnknownEscherRecord();
  95. }
  96. escherRecord.setRecordId(recordId);
  97. escherRecord.setOptions(options);
  98. return escherRecord;
  99. }
  100. /**
  101. * Converts from a list of classes into a map that contains the record id as the key and
  102. * the Constructor in the value part of the map. It does this by using reflection to look up
  103. * the RECORD_ID field then using reflection again to find a reference to the constructor.
  104. *
  105. * @param recClasses The records to convert
  106. * @return The map containing the id/constructor pairs.
  107. */
  108. private static Map<Short, Constructor<? extends EscherRecord>> recordsToMap(Class<?>[] recClasses) {
  109. Map<Short, Constructor<? extends EscherRecord>> result = new HashMap<Short, Constructor<? extends EscherRecord>>();
  110. final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
  111. for (int i = 0; i < recClasses.length; i++) {
  112. @SuppressWarnings("unchecked")
  113. Class<? extends EscherRecord> recCls = (Class<? extends EscherRecord>) recClasses[i];
  114. short sid;
  115. try {
  116. sid = recCls.getField("RECORD_ID").getShort(null);
  117. } catch (IllegalArgumentException e) {
  118. throw new RuntimeException(e);
  119. } catch (IllegalAccessException e) {
  120. throw new RuntimeException(e);
  121. } catch (NoSuchFieldException e) {
  122. throw new RuntimeException(e);
  123. }
  124. Constructor<? extends EscherRecord> constructor;
  125. try {
  126. constructor = recCls.getConstructor( EMPTY_CLASS_ARRAY );
  127. } catch (NoSuchMethodException e) {
  128. throw new RuntimeException(e);
  129. }
  130. result.put(Short.valueOf(sid), constructor);
  131. }
  132. return result;
  133. }
  134. public static boolean isContainer(short options, short recordId){
  135. if(recordId >= EscherContainerRecord.DGG_CONTAINER && recordId
  136. <= EscherContainerRecord.SOLVER_CONTAINER){
  137. return true;
  138. } else {
  139. if (recordId == EscherTextboxRecord.RECORD_ID) {
  140. return false;
  141. } else {
  142. return ( options & (short) 0x000F ) == (short) 0x000F;
  143. }
  144. }
  145. }
  146. }