diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..4824b8026 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 7f78832c0..b5af81686 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -152,6 +152,7 @@ org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line @@ -197,6 +198,7 @@ org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert @@ -244,6 +246,7 @@ org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=inser org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert @@ -321,6 +324,7 @@ org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do n org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs index a38e1bfcf..4ad8c933c 100644 --- a/.settings/org.eclipse.jdt.ui.prefs +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -1,12 +1,75 @@ +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_functional_interfaces=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=false +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.insert_inferred_type_arguments=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=false +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_redundant_type_arguments=true +cleanup.remove_trailing_whitespaces=false +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_anonymous_class_creation=false +cleanup.use_blocks=false +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_lambda=true +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup.use_type_arguments=false +cleanup_profile=_Apache POI +cleanup_settings_version=2 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=false formatter_profile=_Apache POI formatter_settings_version=12 org.eclipse.jdt.ui.exception.name=e org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; org.eclipse.jdt.ui.javadoc=false org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.ondemandthreshold=10 org.eclipse.jdt.ui.overrideannotation=false +org.eclipse.jdt.ui.staticondemandthreshold=10 org.eclipse.jdt.ui.text.custom_code_templates= sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false @@ -21,10 +84,12 @@ sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false sp_cleanup.convert_to_enhanced_for_loop=true sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=false sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false sp_cleanup.make_local_variable_final=false sp_cleanup.make_parameters_final=false sp_cleanup.make_private_fields_final=true @@ -40,6 +105,7 @@ sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class= sp_cleanup.qualify_static_member_accesses_with_declaring_class=false sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=false sp_cleanup.remove_trailing_whitespaces=false sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false @@ -53,10 +119,13 @@ sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/.settings/org.moreunit.prefs b/.settings/org.moreunit.prefs new file mode 100644 index 000000000..659afaf8c --- /dev/null +++ b/.settings/org.moreunit.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.moreunit.preferences.version=2 +org.moreunit.unitsourcefolder=ApachePOI\:src/java\:ApachePOI\:src/testcases\#ApachePOI\:src/java\:ApachePOI\:src/ooxml/testcases\#ApachePOI\:src/java\:ApachePOI\:src/scratchpad/testcases\#ApachePOI\:src/java\:ApachePOI\:src/excelant/testcases\#ApachePOI\:src/java\:ApachePOI\:src/integrationtest +org.moreunit.useprojectsettings=true diff --git a/KEYS b/KEYS index 340f8504d..6e9b6ca5d 100644 --- a/KEYS +++ b/KEYS @@ -1796,3 +1796,348 @@ qoiVaXWfFHwg8u4bSHunrzNja17GyaZHdCEmM9vFzlaqBkoLWCMwIcaKnX9stQJp FZwpzgut7DanaPcCDk7LMBbntaJwRC72M0qcj16SUAdAuGt1yQ== =0DjT -----END PGP PUBLIC KEY BLOCK----- + +pub 4096R/B4812553 2014-02-26 [expires: 2019-02-25] +uid David North +uid David North (Oxford CompSoc) +uid David North (ASF Committer ID) + + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQINBFMOLVsBEADW2N1bQ6GFDDSbC+IKggdS/lwhaEo5Av4Z5B2es83A43boyJZ1 +bn9xfd5TriHubI6VBgjbuB0peoCZye3PzEz9cfZYXsPiAqZngWk95or0N+vwrGoI +9gJM6aBYjE06fxHZRTAi4ADPLW5sV0bT230/u1xpqg1lcko5eGV5sAjI9HaVdfvR +68gQdNVK6TciOeM2EQcTHlRd8D9D2/XTp9aCFynNaFoKmBTOsc+VlczmIgd+1jzW +qWcaGTkEtZKzAxUfxlWgO0xHjs3H4CGqtWWCqj8W1alkwIVHBeXIwHDoHlbmkXok +65jfeQd9tWzTHGXETU7bBbxksbwRlrJrutgolLW+/v9F1je2aG/BKMwOLjF7dk8+ +gvSKlu4PwoItGN0qraWsqAGDR4/bWLihqPluW+pUL544li702DUeZiVxFEb22yDb +p2oWdFafEFhQz4FxRCam/4bfVt6bGLGE8GEd1jeahgmpkIAcbAoI9UOFAVaoSWFv +AqYphVfONeZz7MMIcNlyHth5VAvQQF7/uBWCsNtlvBtVirR+nis+eEwoNRDwYx3N +OKu1GTFPMMHUauB0ORD2ywsFQkIjDbnQMNhwQoC49bs46vCusBb42qmOpjP0viVs +qGI3Ae78F4KEBpa5AVbYRbbicOPeV/tRrHFWMyXmH312898j29qO57e+awARAQAB +tB5EYXZpZCBOb3J0aCA8ZGF2aWRAZG5vcnRoLm5ldD6JAkAEEwEIACoCGwMFCQlm +AYAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlMOL4ECGQEACgkQ+bj6w7SBJVML +Mg//To6EADRjfp11ZGu3cARitfx67276xAkt017sxw76LBzHoF60RtPjcRBBRCYk +0P1URdip6nC2M7Ol151YdTUIfKNWDRzAUVgpWrGfUIRPUgClyO2boTijblS3heZS +gCKz9x3WwRn5elR3Qf6u/wZGIuHBjmh9Jwoa/c6G6ikIoLjoUvXBWR53FlLIpHIF +/q6mzwhXdCwohDsfDI7ckSuSv5yMJsYLZRpEKB3zLgWo4CQP6edaewBd0bVb/Uzy +/5aeolwEfwoNSJ2J4+tQ39U1vxPr1NLEALNl4qW4Gn2fSACnWyEjDHrLltDvolU/ +iLXjgb//9ge93vZUfZmH6vPkrt4TzOfar4wLHTgiEX8nKaOwiMU72wgSL1DLJgry +udf0zSIYDldm/Wy4ggywd/mSyp4oWR3pJFI926CyiQrnA4fSxKrE3yI4Pm5kZNBM +5fhDwtPEtp4F/7kLxGK6MCxyeL94x9QnZdp4FHyRcO3XCCMhfAKT3qLiuHpTiNOt +mOu3Ea1DsEVbSOw+gJzqEZN2ruB8z9DsOxNxlLsdW+sSQRSNgErnLlBLlkXpSawB +imhbwfOHKqZ6eoEqz9ufbrJjIkOEDbIbW93hpyG7zdKSkKsXLR9HbOZ7kgMgzPVi +KNAhc7axmvps55Jx7aXP7G+8c9d8iWhuwD9MemqvhRKyzeeJAj0EEwEIACcFAlMO +LVsCGwMFCQlmAYAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ+bj6w7SBJVPR +6A/9Gk3J6BV0IPuybnmxrkKUicPsIoXgRnzU9LF2TIC6mYJBjb3Tllw0kahsTwLa +vfXEEk971zushOUH/z/wLLgrQ8rzJq3RfbvWRMz9BurIJYGWCnkkINr+lURV0Od1 +IzilZlLuCWCh+WS8w4sJuoziF71Ick3Pf0DCpPIte6PMqBWerrbmXlRfYZgP+vrH +JZ6ZHUEkOVawuY91QRW5HKsM/8RDwgLP7zvXtt7BaVey0XW9pRVQM0fzYzW9wufc +B9DMQeampdXv2R3iXVDQRo86zCRo+7UrqEpBGNXBNhWozucw5eidJo28U+76fWng +7rpDrOPSOUWcg/IfWDrm+zrPyjX/9sFuyjP2w+/dsxmerYk4yXYOQaVHJYaBgAO4 +O11WsjhZZ0bvYgxqJjHs9WGfg7ZfuobzIK2Pl1ZwU0lAcePwuHTBTBFlI6wUxmhG +KM2V8vZUMopxUSw3AE4lWZV756ST8Tc9cVVllBg9eRGHdFN2NKullRzTvLMuUwLc +IGkL6h7VrPmQUhgjyHO4mWgE0or4bm7pHRjP+1D+dxTlr/OZUAiCMgxaBo749Mas +zgvDqcxJOtH/9J3dUeTzN8C1RoKPQPv1znmJ3OgpOKs0cNz1qNIQGQkYasl4awq3 +nPz7QUqcKeZgy/6KIInOPJ8ys2+R54hFhOj/NUBBZID8EX+IRgQQEQIABgUCUw4x +bwAKCRA7Ok8Kx55balZeAJ99U3htpjHcxLxLS9lkGT2+YiBIdgCbBLVVwOBCU7qt +mdHezw/Xp2oxxNKIRgQQEQgABgUCUxNB9AAKCRCgJ0huCLbaUCjLAJ9Iht8ctGWu +SiDFxodDIHmyJ2z8wACbBDGyGhDA5TVJphdJm9Qo1LYKgc2JBBwEEAEKAAYFAlMT +McUACgkQsAucyC163ywE0CAAtVzeWwkCwf5ISyWjXosLnbxohXvmq7uh6bdTVoxW +d1V882pi1UAxU/UZFhb7NSvLaz/hr6+WK0wldl27BF74d6j5rE/3r47KVeOEUuAw +g/J/tLEfzhWtficG13qnLWyf/iTyP6fCIaFRNHL5PK6Br8xZHS0YF9zRHaCutwTm +MHV5KinKktgA6Su7YmGwB3f1lirXxUa+RiGAkvg8tIs8Hn+V2x+FDD22QgW4FDh4 +CFYrzz8NsUiIkYawlIHQdnCkQqiFii7MZOG+EsJ86P0lfYbfJfxEY+4nI737YfXH +SCiWjDTiZG0Hkvrx3qbt0L+Ixydn3oGkrfP+ZngPBj6n7QkALAUFBA34+cylobOD +jb1nKGM32iqPx50GpaS3KH3WmqqXaR2+6SbUUdZvmwac6vQvtRRfEhVtWB9irXUS +wn218Ki2EgprAHwrsvLeMJYoR1U9v1UvSrFj5qtiagJYecxDhsM6ozHmcB2PKdE1 +VkIv2vPRzVsfuWeEFnPOSOODsV1Zu00AfceotvAEZd+VdXNkJ3MfWEy7VT52FnG7 +FntzqDXxGkYZLxK6zn0Qh6udvRz65Q3G0nd+USkAmhEBMTr1/La1LfMAibyUyiyL +0bTRHkjXQc8SpibduFzpcWyrMELVqt1PXgaqtujcjVoHwo00NgJIedBosHVuGBXW +PpUQx2DkTnIUn5Qkncf8SpgCCGFs6Z3qwcqrc6Pb1Sg6XQ6GpMTYMZO0yaLdSSrS +vl6wdiJAzvlP1haafInnNFAo6qgaGNgdiSr1r+SpYycFHORCdqimLax5ggOxh1Y+ +V5uZxDDvOSJQUNKO8bDfREke6gIsNRCj7hRutz9F2K566pu5Tn9UAiv1ZfqYxBub ++mkjkctRw61DlqHepJkY1KQTLBphVM9CAADzWPKGRVZtjeYyLNPBap2GbciBQgzr +/2UCCWAGraxpniCizgkFRPRFaOSp4p0p8DozR3/7xftLPXNgudUbRjxNlRX+uPj4 +0jSEJT1Yrc1/hKgOWvmP13WTbT9/8F2tT+Gd8DTLHa2pXMePOX/dPmF7g7IiEUo9 +Pmci3gFMd0MU1+tgjGZlFs771MZUBnq9rrsX6K5PcikE+UV354mTuF/GdL5Qvwbn +7DQ0Z88FQ4jTatPucEghTLnO9ahB+5ZlE9ri5hWTKRMZNkX0KlCcgcNpPTJ9Ya3e +vWUnuhPHmxq7jD0Fc8VLjiKMWSMMiqTrxdgit41ocZinCH54JKtYb41lsH55rx9q +8crmWdsIKC/Dru7h0MXQW0iU92eMOxiCbXuwNqnzYxWkhjjydhUXmOcufgzfh9Ry +S8zBC/rw5AkhmuMEZK9Ksskt7SvDPqdd0209JrHt+SA8G4kCHAQQAQIABgUCUxDx ++gAKCRC9U3Jvvaau2NoJEACzaTZ8rR1F8+pIy+JdUfQxmZ80CI2CMCjUt+WieiRz +3ZH2sgKqwx4T0c53n8938cwXmwdh5xG17sGWDS8VpXUQ3eq8nHPbc12zJFOWM+Ix +fUIT6zapz18m9x4BjfP78QovU5OyqeE0KtvfwXNvp0OjdoEs70WCaGdmAAcpOd1N +Einz71DOtDcvRdS7A6jqUwfohemu2iPGj7gvUoykb5gg3Nql4K1zQg+Ymo9RH8Bu +MA+ebOvwaRaozi9q1Gjg5erXsN+H9TivoMwRiAHdlfeETuGWTFJl0EhtXMHiUjpz +fA6UsR8LgRMehar8rcsWRY2x8oH6L7Wf2JLc+XnZhAe6wKij5BlbJrJBZc7FcoMJ +KqxGlgLnMDXL5nmHfaIxiJUU6qe9DSRvGyMB1rr9xxeHp3s9DVR8G6Zaub6ufa7k +8lfCKbJBru5UD/FrWPMNztiG8fgRg9krmU41ZgvhT5ksZmH5rcFgK7IOowiN9Bxg +tAclbURX6uNc8CYmWVkR1f+zFS2ChPEebyK+R/VZm0WH3Rz6tacWUtzxr1GryLUU +wTmxGnyXflD9ySAkjEO60NdwUpofeX9qMzza/sJPpxZsGmy3PHByS/AhK7wnPSlH +52o9BTVqwY9b6B+oOnswjccgoNyQmtQu84CnGlUKG0y40ho3F1DCHH/l4jrYaxsY +J4kCHAQQAQIABgUCUxHKygAKCRDABX5xTWlPsl7XEADlAVK6EiOs88azKcH6h/uY +luxi8F97MOEcyjKrfliRxc5Wt2Ry417ngVelhrIzZPoUi4iT8znazQ+GQWBHS1SY +51AEqPN0wrbLpMnhM7cHOZ+Yh8za/G8mIpXCInrsFoDsGTm6jBuwhsmD80HJ8ctq +7DTxrxEfklPuKmQ0ZgbH4wwEmTeU8pzzLlBe9yiDOYVXscG6xffPp6Jml+H2buAb +B7zZKD/yXuNKgs7AonMLrA6d297wslMAZd9lZ67jmLvWLUhd7LGaA2xVNO2+5yNx +gMXrdL0wY6NdUY+yy/48b8izD4Hxc0+7wfnZgeND2tgg3av+hbX0sRbIoP7uZgrl +JKuYuHpgmzQ0Y4eoMklWiWl1o7A8d/vVPuGSOztXUhlQF4nKfEAyn9pFyu4UXjfu +NueBTQl8Hqii/wN2nMk9vZz2xFN2bnsqvIhjnMA2yoQl5bs576yj8Rbji9eK4ZUg +WMAkuOkB675DX5rYrXUnDNo3aBS96NQG4CbG/jaM5i0a+ClVg9tVboGksBJZRzUs +lUQxo8AXS+h74iipJrokigsrq20jO2t/WdxRdxduXu5IOs+hB6ae81JjjHjTFNDu +uteDnnLNG1dBfebw/RkH3cjp+lsvnAks/mINStMoPEH7/Obvzuku32UvAxglkY47 +QSCJfS4QpkD4G/NUvNFhVokCHAQTAQIABgUCUx5jgwAKCRCtltamwB49Z5zGD/9G +Is/hfe5iQrSP9NFNChQjaeafjprCMfi30glYsaXM3y2rrXZJh7zKAvOhYcZwbWK2 ++9meRzuMX2P2iG3WZ7iyaoPALb1WpPlSQef34g3SJRV1UDVKwYpkJSZCsqIX1bhB +sr4qjY7pN46B7GX7RrGl79qDy/CUzLciJ1bX/BiB4L3+ls4qrrfomO3+r10ngqzT +MMmn5hjVWE1BDcuViKYwhW0u/HcTulIVkIp3+Vs6nX54d7nG45YHdmBeLPA5fEFv +Xe3Q3Q0YwK4r/bZwEqlg2GVg5npYIB7SB7MbU1znuHJvyUpTeO0z8lNWjYjKFedb +YmO/tQSoJ82GQt9HMaENKxKP4Tk8Wr3SV3y177nD8+6jFWJQZ8lqsQ/GxZukFWPV +0Eo9dRsQx5v+B5h2213hK4YcOhJaiVtBggUodIKiGz8sW89V2L8EATMb3lAJsvPu +FiQkuQDOhDlbqAj0yQfyBxKmKCHOfAJ2Q3aYBhvFFXho+DBnPjS9r3QfL1z3UYNc +Y8tCT9Um+MX6h/2iAodpxtu4xqHd2PavOxLsOA0IFKIcSNOp731VaMPdptgCOoCk +r7JL7PrH+7QwBPQzCr74rQhiTfuDd1vbmgJGm/D/MuPX5+KemVqOiE+o6xotCb6Y +KqAWu9CqW2m2L8QuD4hNR9NV+StJWmmNaCoOOXZQXIkCHAQTAQIABgUCUx5k3gAK +CRAObqOOk0fwLFbMEACNkB4OlOW32GFzalq6uf2vmG9H99+/pBiKyGKvc50obLwK +x4g8RM/dH6zduHUZ/uJJ08Qvx5h53JVYPOdxk7cXvWVnFJXRQNqgRotOLj9r8Hpa +Rijh4GrTDXeVrNY1rw+Okw7v2iyNwWQDVOkAzrg/fZ5cZRp9e2Ti0cN4COcGJVQJ +lHYfa13GuiSUSdc2OisYiQZWXdT8SnjHLb5cL6GRgmDDhOC/FISiu1L+LFIsyXoZ +9pzFY/43sGTmZJjFnudoxEQHuXmbQZ4Z6o0yAncU2bow0QEQQ/949z4GHNcbXduz +eXBWXO0kA6z4Lu8YLBk9ihrka3kw1Y4VtvIuWQDuLV7DR/k3/YHZzUUvzGH3c8Vn ++DTK5f/dp2TrK63Py+x4/7E62V9uk/VB+TVy0E6vic0Tk3+KMGUHsVWGZiYXYnso +ZpVw7/2vMmiPxai35RMe/yi8r7pAYrQc6su9o/WMS1Hxhp3VPa/g4S/mBfk8jse3 +tHof6ZTYAG7t3FhxVGXgHRYa0nnmHf9bLtNOHrAJ4M07z1VB5wMkFJ491nf05oVr +cyBA3swvliwAilskCfJFFy1yttnOlYY1hLVq7fUAoMfjux9BZglXlmCPp5HlaT2t +rF6VThREOAI8/Es/zrYAgntLuPFLJcYvjqPEChttT8I0H5KlzoSMfHZybsyW04hG +BBMRAgAGBQJTHmQGAAoJECKBkcFWfiwXbtEAoNyetrXS29ORsTlasGUPwumYgHaa +AKCv7Ky87jcPLoQHLp5ugFOyMAXKc4kCHAQTAQIABgUCUx5kQwAKCRAo9QGWxDgC +6wDkEADFhTXNCEedftkHSLl6GxWCGEi1qI418U+cn01hRCtIY0nVjzGYJaxHamtD +2cepVSDDdIeXj9C4mcy3na0/mME7+H/tLuZiOv5d5rFIIK6gODmE/69LrCGSLJL/ +1ULCQMqQ8IcKDEkZTmStEKJZPvE/lPmfjn1XGf5gC8zbTg59hN6op/bRuQpQHsIi +LNn7jEW4X65Ygig/HcRK0Xj6iTEjPc0ITMthLPG5XHUjMeRt+syc65Hl+Q18zwsX +i6bjp/DKLgDUdLvmXdBSxmsDZgZjJtfE5C/C0Yom/VpVesXCWCZqe++GT/K95dSq +pZbu0DSVKtrSTqglRJf3gPeVwQUFixjj/tynZHiO/7cZq0pazRrX2qM2ZZB1hkhZ +VkISzBMUFC8YPkbVDKVYisyUJLdUEKdSB18RcX/ZxLUOsYTo3CsUIwoTH6aL4yQB +C8rB0OkbJeaZbU/3dlHnycAas4ze6hzvEdiYyb2jrg37qbJwg0CPDevsNkLu/Ie/ +6BqqXcLszWS52aNcyLMPTpjvQIC2gV1f450chsiw9yeMUtsgVFXADO6+8zM1io9B +1dtEjRXvaiI3jD/jqV+g8TV1i411NHw5sW9c/Jx0UuXDa7gmb6+6VvavIHCF0pLL +FKUCMmoFePtp0dvdqN1Ysv1RBn7GKl4GGImE0dh5T8pPlXc57IhGBBMRAgAGBQJT +HmRrAAoJEFk2rKVTkFoB0E0Aniydu8kZjiaob6/OT9hYtOkLaQRqAKCD+l2caV7i +J/SkLCBgY2relojE2YkCGwQQAQIABgUCVGuZsAAKCRAXscp9ZAiVKMxYD/iZPK6P +qwHxzEuQjquo8f9f0q1RkX4AZa1j5hvXcqAddUa3HpihHDFnW0UDpptlyonryxUE +imhD9a22/eIsCz4sF8gAgrp9b1gRBJmJMvtRgVHaFn1u02/5IEvRj7JsWgVXzWFU +yh9zLaiQtcpfvfFzmdZKtZ3hl0TGl8NFMLxUsownR2tx0iuc8r+NpzzKpxQeXlYS +98DrDLjE3AKVSZcc8DUBTlwhCZLiXEaQjAKXW+Mxfg8C2E4hQIAsqLWhj8PRQEpG +w9F0Wdrh9w4ePsKKnzsIaprkRve3vzEuDLvmHV+9DQd/sh+C5W1LjL4h+vC0eXhd +42lIWrfgOhai2rrwgfSNEFnMAsB1zdWcwMgVSP97sSVfyrqMlDJWXuW8v2KR36ws +zZnqVPsgQk0Uy53mItUnWblgabSb/udVa+ZI6NeOv1bMGMgKaFqXCn6aHD1X1/E3 +0XtCy2dE6reTAU0zNaRc9ZJOLvxJj8ymP+pUqzkvxLMWAuqpCKsM6YNFlCFkzdfO +LHxhqGp68jKPUfuG7z6yRkgDZF84k55SUK7td8lHmJpbeiL1+N8Sm9CujQ+TEAbA +ZFAQjonwnzXWxzI4N+1TWM8BbhLmFpG814JNxyswYdmps6pdKCWHi8zC60dYZ6Mw +IQZfNWpkeLh7W44NuSJ7pIXuSfEaFCKXX+RwtIpEYXZpZCBOb3J0aCAoT3hmb3Jk +IENvbXBTb2MpIChJIGRvbid0IHVzZSB0aGlzIGFkZHJlc3MgbXVjaCwgYW5kIGl0 +IHJvdXRlcyB0byB0aGUgc2FtZSBtYWlsYm94IGFzIG15IG1haW4gdXNlciBJRC4p +IDxub3J0aEBveC5jb21wc29jLm5ldD6JAj0EEwEIACcFAlMOLj4CGwMFCQlmAYAF +CwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ+bj6w7SBJVMTXw/+PqnnuxB7vBpk +/rSeunEmZ+qhswnAqjazDLe7gBAPZXKYe6fIdBu0cZpPc1dqlKUY7s7OAUB/egF6 +nHZI7Ise3fq1PJgh1ZKXHtJv5tDdIHZ7H68H+1f+JxOBDDAIdhbr2sogoBRkeYxv +qE4H4oZt2Ntp474ThU4RHUjHaIVM8uOo9f2xvy0hCUGUHPs9lM8l293LwAtwTMMq +unUzwXQTnXcZv+4AffBiR438u1FFizRKxiVsFZanAWdzW4Es5XSpeSZYsqofR63i +lYukjYYRUYjqtAOqCh34hHdUCp2edENG0alSjHded+T1H8WtFARTihyb7Dd5oMP1 +wA6pIzhhKXl9eSMXqpmFvPbrFiD0dlOes/guY6smy+z0S3BldUe+vqF18hhIHpIC +NPrPc354Vg0hgnsx3oHKYcD7uMAS/vJrOUfJV+xFSjySHadvX9U10Blv9l18su2b +AT7s7go04eEleKXJwaPVaYZUVaWFmd9WYay0GoNg8aKjke7Fj8cvPhmhn5gHlbj6 +9BBot7eNcHLEAYvhjiO5kBBYRn0skEPRvgxapwddG+9VkpYWi34IX7kC2c1yaQAu +GQCio641oribB9PDwU2gmvr5L70XexkxfT6Jh8L3Qur0gcnKKDRuqq9LHAAen131 +DpL+Bv2qmYuUb21cy1JYVBDpbn7j2AqIRgQQEQIABgUCUw4xbwAKCRA7Ok8Kx55b +amtlAKC3RJdB/Csdw+gnbImjWoVGs+E8yQCgpeMDerQA72Py4Si6qgpDEWFhOhCI +RgQQEQgABgUCUxNB9AAKCRCgJ0huCLbaUJXOAJ4x85jehtQViJV2WmteRuPQm9aK +6QCeLA4NmWELWo1X+Yeyf5iVPH3jp+6JBBwEEAEKAAYFAlMTMcUACgkQsAucyC16 +3yw85B//S1KwKCIKAlpqRP4x/815btZlDMFr1ve4VkFoSiCAiQTtreYlKqt6Ia8s +oApHgvSFmCFo1S0q221ohIlW2At4BVKUVWqkwmEzGP+uImI8JzjfRWkfZukyXwYt +AbDaaKn6nH1mP8gIsaV3Y5jM7mcfcLZVpiXE/+UVvudGjixonN37BsgHV+9lp/AF +IMs0rH+Yl0tRFpYfAWCBwP3ZVOzyPbtN1gVKc3LXMhPOBfNG+7knFzI1b0eor/E+ +0vPXZ4pZEknRtulli/95ME0WkzFbvz0fx8AVAYWkJytqDF/gIsjiCq5FNAYWA/7C +T05Np/3g5IbTSceH+bywHA/BH1PGf+zb8edIRhzKi7GbtcHm0kHSiRTnGEhDqy5F +RDy8WOI43KMw1gDV2EhS67Ns4oMa2g10RZizTDFIhQeiayxM4irYzz0MmWvr4SMC ++jU+H140MxzD+VeZCbpPTBgFoMAZV5RO4bG6BiPFZ4bKGkXaKteWcR2Z6xkyLrcm +rV1OQw6tKDslqUJnIgbr4eQy8PmgKZ+WZi7i30YZU62nOzzK8FRgBcxULbF4QF3L +/T282rBM6YA58pdbBTQZ8RQm5gsl3zhtIC5LVPMYHAtmm9dQpZgrrrRhJYzJOCte +SJuIh11vbK0b6THLX3jzybmgeetcBzI01gXSAhnczQwJnEjvxRA84blk1zAFbZyI +j5h9+XGnCLGmupYX5yKoJ+IQyvPJn6yO1cc1gMT30jCK4yRpGcq9spDETxB9k/oC +tYXu4db0LvqhIsiVYhBzha5x44WxwOysnMCVcSWSo9Xr4HkycbxstwvZVraT9oxy +9AIjJJ6ZS8ntCNGUofxeSPdojyz6B+LXXrgOPxh5yHVH6vDfFQzgDTISTPO4KNWB +vOMw2IXhcSNKZzmk8UQBOHTCQ/Pyu52Sb9MDP8d8nPCfVxZjiO+2PpuJnraL+zge +BlIOm1mLMZelYJXyKF7bkE8yeaBtmCR6bgqpRsIAuw91wxTXG0/B3oiiVW3WXi9O +611ycF4YvjlB5boAC9t7cxS2MXFFE75Zh8az1LuEkgq+/pJBCf4v+IXxrC3kxxLm +OPgu1iPVuDigviWbftdAeLQ9bsQSQv0jR+/jGQzyQllxHq5ar4zKUBhxRlke4jHG +KUOSyYznXQwCGlCgvKWLaY2WMjrPuh5vAWbDKRvORlto9Jgr+pcD7H8Hs1380eE0 +elBcYtlHO0mMSX66ycnjhNRLKzMUHZMw+UO2mhUV0+9fQmfGR5u4996+usiu0kL2 +9x207gBN7RKDZ0/XVuUzXaHuS8rY0fhuSj2C1WIUcCy8sTvR9tWznsCG58GsP99f +ylrvBtKg3vTLjsyBoZFsfDzVmjvVuIkCHAQQAQIABgUCUxDx+gAKCRC9U3Jvvaau +2H8PD/4+g4mVKclHKIcrjjKvmB4Y7iqOcNeI/Nn5HB8p5Vz19AekYDWBbJX+KxPY +x7puto5fNASl7LMAFbNt2PVmNJ2wBO3Duda0weHooIiEKm8aLGNWw2BjQYkwTJKn +rO7E0I1FkXxOByZQdAMshILthfRUZ+jJ2uNyHgCgU28TNoPSUXgpfA5e5KnQF3LF +0YuFFHSmOFsCAmMO5w/VbVwZxvsj/0CMW4mrIBjBvcR7zEhDI/cefhzXcU0JC6lO +auyca7NuYs2ytqWqB83wNXQ0zBZI8X+lB3mstKn1kdC6ajRdM4VPn29Hk4bxqiRW +9IjL+pmnm6BWiTJV3G3givp8tsbtI77lrLfE/RUinEO16QJCs0oUcgY21n0aFaWo +3c8VA7ThrAvINiwHwiS/5C5FfpfIzUBcOJXMaqmRdvQJ6Urxj6R/P92pj4dZRYg4 +iJFl7BJ8VeG2ecHaE/d5VB9r52SRCtCAckeLDUmD69xF4k2kYpwqf9FgwP5N6D+9 +zZkL8eqotrIoEfrc4d5Ja3P59Go3Tw6P715yISyTrN+qvHSCnHw+ciYEDN6cfVeo +mi93qU5202ZYIGDFqWzYoY9AO7rk2CIYkul14jeq5Nm+8EZjtghg+1ADqS00ojoq +LfxIMmNKDoQx+Mb2PRUiJYbA6MzsX5JCDk7+N5gR1zbrqqg1gYkCHAQQAQIABgUC +UxHKygAKCRDABX5xTWlPsoY3D/9sDReRlVGBiZ6FQkhRVjv5Vv16mev09oRHinK1 +HDK6gdfOO9UWvsVNoi7qTillY7dsp4bAnFvuu0/FG58cD0LDqJ4gzFO6ZRqlUtPV +T145SatUYuhXv1x/+pAK7mIoVndMvplcEjP+mJl2R2G/pGVDdJRJ+AS8MGLaO+SR +5ITUwvDllg2rr7HTnxwvT4mMzKozFWlM09cFMU1LYysoh7YJlwMMcyEr7Pc7D+G8 +r6KSQJA2PNVceCICiEvNOd+BsBQuEuAQ3qnBfQ2Hr6GyTtkGKbu96b8CjV+U2chf +BFe9l2ulVhtN2X+RwLVuYHFBipg9oOhLZ2cHjTSPV96+Oiad+UYplTufQphumjHa +1FeH6M1lgB7cANxBdGbY8ZFc0wtbYkCFgsUjSFlYS4AbVcTrdlQvEK36WsQOP1uV +s/pbsCDgH+dKtRAPfUzSre8gslyj9oGuyqnTsIyCpavSbL09UPPBxQEUsAdlvOCs +p8KpXT4/4DRcJvvMVeBtYHHrEyJ1oIdWJd58m4Rls71Cuc6OCJQYkLJqWkbFtegA +rqoVYEXPjXCP0zBkGblsZKK5o5r9m6tDDbzqamSg0AfQgDhbvWGtjPXLj40VB9cI +J8ntBYyuFAO64llK1qWS8BlCSismWx7EcVpXIr3umCPGI/aa4/S9hlfrFqOGmZy+ +1+P1sYkCHAQTAQIABgUCUx5jhQAKCRCtltamwB49Z/KND/4kU2frZUkl2GXF/DO5 +wj8wk+9nM8zkhqC6BMO8quJviNW0Bhl4OY4jwVjiasYwcPppDyZWW9WAAprECCI7 +t89mbvRC/B6KIl9n5w6jCgg/jAITZ+YajBMmZxdD+m8Bc47nDp3iQubsWMzlvA+O +OeJWc0Fnlcv49OzpaU3gAD52evZTyrpjRJ2zkggLxJVmpOQVmqHdg/GGicJHVkSo +YfDyO1IAoAQkzN1OZRBx981xa4hCLIF8DOuBC6Re+SgelVcODYe2dMQnDQuhgfeo +DTO6Raf2UDdfYcV1tbEZwO5+UV1sPbRhfyu2PYpTYWoceDPu8SxKTRFbSGpX8Zx2 +0PMkLsPYr8+iY4VciLOJ28CKwooU6rGm/LNGTtKRymd7oalHiM4DJ//vVEcZ3P5X +666yTbgZ8n8Ui95KERGSmSQbr/VbsTivUaeL00On2IxL87j+31gjAC/8zG/it/5f +8MRozyDl2R2k05wPZtg8v48QuarKbLR4fzI5flV9Jqmcyn6THSXmUJftfY+cGHMk +/SxCtzpL4w/v7T7nnKzD7PuWPVd7KGJ0A70123A5mbw1KvaQfEJotwW8Ym1fBaFv +21A+iz7KrmGkWq8I8yFpiIuvjTF56eJLp6AM6Xe+K7mxvCJnn806HT1qe8iFRryb +GeaGoLj1K4vbJnxFoU1wum5JmIkCHAQTAQIABgUCUx5k3wAKCRAObqOOk0fwLNCT +D/9ivD2rhfPAoQ5KSkaXdAPHug1jdYkZCUyK8XJl7hM1yFKwRDEjpYZOb5IASo2D +uSvB5oys1lfWaYmM0LgSL2ONhvpdsrK21y90dH5o+DM81hhVSxKQyvXOmg24G8XJ +rco+y031iDHdsjNfJH5H/OWITTqKuDKmecQs3Z48zTD9Vr3SkmVlWtyptlc19Jzh +M5FLYIH3Zzo1qmDyFtMW7h+H1RkkgWH+EIQu0oLePEOTkKNcZm8e1+qncgTmcdH0 +LQr9lonWdR1tb0dB00OUa5pmzFaVqmAHYI/GmUOyEIGuiAAb4N5JYTKxEZAxxELk +aTbVhGmzh89mqt9tuFIwjDzY9vgh50EM+7XQPqk6dwm2RufxU3b/ueEUNQyWij3P +oJCBZYE7qCsLL8mxk+KLMSmsmglJB77TJm1XE7C43CBpTXMv7MVnjIibVp6KVfsE +MtL7A/mGISZHWxuEgG8V4CwM9eXU3jnVdg6yXvYu1JN/7+qebNRD5SG9a71nXQU4 +bEsNtYsC+FcF2BhC4JlWME32O7kRueBrG20O7UlbCipPPdAwEAQW4qHPlO7PQic3 +AqUmvp5ovyAxzMwXkkMYDNdo58eh+Srsi0uOFMXP48bBQLcG/b1/PBKXaVNlBEZP +yxzo8kp7Dh3+gVHsNJ08HcSSf5/ExJg111wTqVI9gREje4hGBBMRAgAGBQJTHmQI +AAoJECKBkcFWfiwXw18AnAhNT8OumByLV/egAwlovu4x6B9eAKDDUQa3pWjcH1RD +BQgY56nsRmP3fIkCHAQTAQIABgUCUx5kRAAKCRAo9QGWxDgC669YD/sG/FxpU2rx +8ajhDWRou7S6VkcOc9LqoNjmgklqCDdVzYpb0MyTeYQB6tkkrCrH0SiVPAiV0582 +U1AS5iujoxBEoeqULIQOCOjtDsUFpUSiWBKN75b4SIQGdUjZRSlW2WpEiznOIew9 +zFoWFnUgu2Oa6mCHEX8RJr5hnq541xmwSahnwoLC7O2ZzZjtsnoS0GC3I2PYW3RZ +S5Vb2qhGMur23eGMycqxud6PAVL9sHrdtaFpkXdxRTTcxdicHMYca783ZXm+Ikyg +QTfA850ezt2EeF8DcYT/r3Q0eqTBxgTEaJOUyDoeDAbaZUtSw0dEAcOE5zwfP222 +WYdXTaeGJj6HyZyyW3/BLn9Sp8dzsc0MxIzjSTWihE6D3Kk9FXK+AZEl4nPzah5G +oIA7QSyEIQsQWOjhcU6Q4yy1ACns+2nlZP2IWsbolIMgfPXCpGT0SW0lF7bGIvRy +ZnddnvIoKPi5uvto9woq6a+6CD6rF7kdg8j26mjxVcysX0T+Ajb2DWCEAjYFRBvw +I04HLZT4owpVQLLME0f8GIOuI6fYgGR4nXLb9obrvjU2We3/6ShqvmDyNSH/xJ05 +qIsGemuhisAk7RRrZPMphBwP9BhxvNljjzukIWd6ckkEQe61DixjyYFccD7b4C4z +ThRfbqtwL69fmUPb/wzs4bfqPwU2Vav6yYhGBBMRAgAGBQJTHmRsAAoJEFk2rKVT +kFoBeNUAnRR70AEUF099PtlG6DGtgZnq7AJLAKC8dPOV27zhMZc8J+Kqgdo7H+HE +zYkCHAQQAQIABgUCVGuZsAAKCRAXscp9ZAiVKAktD/4hDcYJoDMQMbq1aApcfl3G +DDohSdqpquAigGNXZ1DjjVcIe09mnER+20fZOCYMwemzcczqjMj7OB961bKyZG4Z +DaQ63vBPWIa4Z1l8u0nmQp1bAxl5BYGnFeguAIgcn5bQGN8EG3guEEOqz3ItDG+R +OX6VUitRjJQcAc/MVYvk3F7flnRt9WlAOlsBMW/xAFaXamlABAH2+IPYfCeZfWEl +pdDl40xuH/MB5YzsaBqROezakDh9R172SnebFgibeqBGtIwaZ1KvnvKbWPuCZZZ/ +DuyTMkghAKgp7U28mtR2xZ0tMsT5sjXgZTMDocnR3zkgMeDw8NACpYD3Q5GES5Z2 +TImXXzNbiRlmkcZUwSEEhaD2sG2n5o28OHidnUq9LrRjfT7qH1y4ChbTvpF83XU5 +7OtyqXEDav8RORA4gMOKoyLeQf5PEc4QhpSObOKYT+acaJlpc8I7BKgjy/muqO/m +WkdKRMkNwmlAEPpI161gE2LbRfd4UqtaikVUdQzFuEjt0sOfq2676k/Dm5ubMx1X +PuF+dS9e6kwPUfLs9bcrIyZHrhHWx0nW7Emg/GVsuMbzaWYSxBWs5PfoMkR/fl/b +g4INzoGKiWl3W6TAQdgYwlzzlOSy47ETXjsk0eRAIzbwN8E4Sj+FHUqWBAVq9tU1 +GOycWaP+95muxZyQSTWKCbQyRGF2aWQgTm9ydGggKEFTRiBDb21taXR0ZXIgSUQp +IDxkbm9ydGhAYXBhY2hlLm9yZz6JAj0EEwEIACcFAlVu+0kCGwMFCQlmAYAFCwkI +BwMFFQoJCAsFFgIDAQACHgECF4AACgkQ+bj6w7SBJVPdNg/8CqkzQThpSx/bWEed +e6es+DWvVzppNiwwM/y0X24EbObQARGOc60Bqh0GcnGO/oAj8Dr5QozutUmF1ZiE +RX/BSBTdQvfGDtWj4I4jf7rbusFoqulF8ECAWjiF58xLg657NpVteVxbmRKTtLgD +H7BRTaCsxgqjt/2jjWf3LhO9QqosDYBZ6i109aSgNfSrQwYHRi0qQA50Yp0tLpIo +7udcr3GNZZS71MhBSwfsmwP0tEBhI5WcDkgRY0IX1VGpgapO6fwRqB2NOeBI53ap +4yZq4Rhc2Q+kZS0v2Uqg/42JfKasrKzhkL2PQI+0d7rFatgsI653viobo9Y/3L08 +Jq+u6st0htNLo3XHxKMwvV6CXVBWA6nylOGjLnzA/sRkpkKxhSJ1xktztPrn0x7e +NtcXSq6tZTW+uHmdjXfLyArlqgIVOxotLpRPjI1JAcYnwkv00KWtVqzpMGKmwyoO +1QOneHE52xbhx/yfPBK7uZHXXtMb44He3CfZM0Jfh7gZwVu+6k5WZTuEysBBTuNL +86wxbSBwNRByIxVL64Fi6UsdvbzE7UJmFohygeo9myZRgKLEYjnWellsaoEkgJ1P +s1RczyOPJbVeU0PQPWWn+pVqqjgQxE6zaRu+JfVuMyHQM3SnmoyuZfciCVrJd4EH +h+Qrcq4frzvFFmkB7sdx0//Jp7u5Ag0EUw4tWwEQAMOW2F/ARC8Qaco29TnCvZtz +q6szMgWoMpxd1vfOi+i6EifFAcHDEdyBIa2CW/QMh9zpRQamO82iIOC9wBmcN4iu +Bi4ZH3wlxAAfuEMSwdsmPVfZQCgODZrlkCGr/4bgHnX5VGFiwlzZUUDemfIzleIo +d7FzHZ2zIPxUQbMmPriS/cxUry635fZ0Y5YRlgq9AJzif0hNnx7PnZimxVx0hVBA +OJmDcc4/st3YwKvCqEuKgaJDJNE82WE5a9KldgPtQdykmyxaKMneht9b8St4lZkB +Sdz90JhSj1GPsDNl88ui+BuIbgGWobAYVW9gY2h/lP95MM1YNtdBAdcyjGe4RhA6 +T+JD5eznikI5EIOyb0zH9CiVDO0CZVH7tuGtJwBVaRSDTtUdNeR4k6xczFjWBmRr +3n9en+JD/LrYPN5b6P5Cf/SC5YhVD6scaCKdQFOBOClEKxa2dr5eu/7JgsyJCayA +dZhsHvph0rMVnbSK5DepiRAjJRryXiJvFOD4PbRAyoaA25cSRbjYVN9TLdMhCnBZ +Nol5z/AxT6ZH2E6CmcvlFfVE6UhvZFfmF7zHTFxvU/eT4kdd9xJZcY1I+y+5bzm3 +LuKIe5W94DpPJ6aebyBX2rr5OXrK3jILjsk+Zof0nxk3SOOKcrLBhs0dtbA8gv7A +YIW5c9iKjl9X8i3CiSjVABEBAAGJAiUEGAEIAA8FAlMOLVsCGwwFCQlmAYAACgkQ ++bj6w7SBJVNe4BAAxmSonXAhNxohcplTKZpZvzqzU0+92PGIj6D17rJDy18N1DI6 +7bU1XDjIsR5OC/JknK2nuJKimhIymDJZv+b2VLKEZF+LW4HzPTsdEdHMyzW7WssA +uQGSnHmELagkUnXLk12zbcieugctN8y2H9efuTL3tl9ARkR/Ns4MhVgzP+2XclOW +V04fa8GLW9dC0MGzZQJvMk2mzs/2vV7/v1ve3IRZqeLDmpkmZSNTpdB3tUmFARKq +SduvInOfNqPIcRheVz2TwhghRnwkzJHoJ9Bk+rCThU6QLKZv8o4bf6YKPMkY5z+l +6S9QXf33vNqwIUDn5qxayT8kRz7/GSChJ9twXVVflb5VTTP5FVNUNjDYxCuHBPlC +UisOlrHjk/jYf8lX3+JFiUMZN+M7wZIakHe4SyRjMEHWUCnC+iObMP0KJ+DoQJK1 +0Hqhah9I+iJZk8n2WkYp4kt6QSwFi+g4QaLQ6byVbBeYA5JPTikQJlpbVgKrKr0C +LaodHywrloaA6lW+e+WMlx9T2t13s1XQNxM3WnnRYYMh/nEcgtcw7mZRL6h55erS +NPfXcVvbo0b+iing/HrOtjK4xU0lypGlQlXcfQcMr0RaNAMv4ExgIzQj38jMzNaw +9a52BMKzZF8059sQF4VfrIVt2eZZyRUa84QI9R3um3tAho1ORUaOtEyOJn8= +=keWk +-----END PGP PUBLIC KEY BLOCK----- +pub 4096R/27B9F635 2015-06-22 +uid Dominik Stadler +sub 4096R/EF9D5EA6 2015-06-22 +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQINBFWIY8gBEACj8cTCDwLduEQpiO2M1qL+/aMtct7IN9l0BIV9bL1oILyRBdi3 +3DHzP07GWLlr0LaRu/uUQuNVKy5ZIF237qn5BJoQnMQuZ2oQPDbaWdg8XkTJJ8pH +kBQfsV5CmConjBJmV1rPCSbNbwYl+3fstIRybqgIjt9AK1xPxss4BUtbwSRzP4R2 +OblNfJ2WiD2/BLD/cw5GiBIMnH6LYc4tSoEdnZEv07RJUcTXs547wfCGMfOZLjps +TRLpCQsTnpWV0X7Y7P9m62OUPEs6XIYJptY/Kv7LaEm8A5SSdTOfe0/SusIa2AR0 +ASb9zAwmuPLLNWhPiHKvXeWmxOgr//tpftvtRGlYYkXq6VbvLyhcjRSPiv1Rqx+W +byvduNzRgJfSXIwfOIuAo8w/aNebZw6v2JDQYsx+P8KIxWO+MEY3XnzRIKEbK5mW +vxIIhZhzXi+CkAYV3gSvHISDiYmw3/wJBerTO5Fs4cBIqMWfszTXJOYsPhyTF8Kl +gOawyq7+kpyil0xRAZ9c0Zq+dwrny/q8Jw22MtWxt0gP1Q2bYoLdNhLQ4NzMGAvQ +2eo0loXwR88cB1LsBHhBfUYnRbw9MXPMaBH0oHdqb+Zm1XvVJMv2xpBM7jt8LxA0 +rWkAg65tv70jTa5NM2eSda2qRMpVCY5VIvCcoEmGvnnZUA4l81um2Y+MdwARAQAB +tCNEb21pbmlrIFN0YWRsZXIgPGNlbnRpY0BhcGFjaGUub3JnPokCNwQTAQoAIQUC +VYhjyAIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRDhlnVFJ7n2Na4PD/9H +GZuGda4QN1IOFc67RSVoLj1fPgKcEiu6zzarzMGChKsdxoo0ZhmyKaAh5/JZn9nh +YlHDi1zpIjbDLEwEqr6qXjaJz2fw50BGX7yamM7pFvtNglu1KfyDLogYFDIDktaa +nHtRUgsTXDL116YfoiJlucRqv/7sTCQC2bsuDaS8jmq5Q+9tVELrivxvHfDqnb9f ++yH9HoFW6lQAPyVHVfpB0nDvmWx3twXjatrNiU+Xp+sGsfHtxD2YUjyft0diw1H+ +1U03FJGG344dUS5ZY9L/IBvIaZU+ovMSjpXshlZRZURzlN1FJljB1YkQgHEdjWHz +9Ur0boQyyMZb3pYc4hINfLChoQoOlENM05LZE1G+x6aug4EGEWnKQsBfVqu4AwgB +zQkaStHnNrmtIlEWzQtz/CZeiWpC0zXwi4gdiu/Vk+XOZE0YPxjLsFVIpK+m4B/I +9VmlXodgUkOcmU99EkmXbR6G74OPYphtlRXRnZVcLSlTKfQitZH96/XBHoQ+k+e7 +uODYS9Zyfq5bFzbCmXLieOTQZUAKL9xv5CH9x4aOcCNeSr6JIlIo8UA4QvP9QkBz +At4H4F2a80TUZtB54MwydKRInKlCdneZRJgEw2aHNuzuc8CeNxBxQ0sXtPRRjs4+ +bKHc89iggbhQCrJBijlV62jrXlVLqDTaNjOkQn20lrkCDQRViGPIARAAnDyvkbv9 +45FwvG4qU2haI3K5DG4KBUgtnuioaK0aF+GrExkIO/kjR574VTcCyTr8PBbYImOx +YNaxn9QVG9tLlISworLscur79XVcayxkI3OWFzmAkjtlgrGiymTDmIofIXIh6O6H +NkwOCkfYV2KcTO+UAf5O+DOPi+YH+Wr83GlbxRSqM6XMIXSkva3wPFWXaAmwCi1/ +JeUyEMdLWkEUfNPA53+1cq7SQEMSzdwEfazovOd4MUzQBoIDYbRdio/UBvTw/sQM +BpKkjrDqa/Z7am0+TjgmyzJVLtfivgKP8/oluwwNa4OJQNNp4kSqmB64I7YXd9dj +3FjdaVXB6E8BqOxubN9MDBGy59YOkQW6eeYYWH8zRz8BlaynieslPxZjBeEgQOS8 +ow7RRzyALU4BWrD2WBYu8Po9qr26r0NhzwNtSGt8zeB2rK+FMoKIR/EEJUqKgdWR +e/8ase0Uy70NQPqTwcZRDYaDvdvfK5YafIVODwUu1ojHqkRdPuRH5UpNdaCBk3kU +0P8yTb8/qTBee3kLvkxspaMH1kgmUSWwsR7vip7Mra/fTCLZJPhJdpuPxHgd3MtO +CgTNROlubFhHcrhjOkVTWNfoNbi1zaYZI70mzMasA4cqxMCkzhHDt61ChQa0u7Jf +kIcGBZe11QeTMmQkUoK+Z+/RR185fPtbb6EAEQEAAYkCHwQYAQoACQUCVYhjyAIb +DAAKCRDhlnVFJ7n2NV6jD/9qaa+oFiMEZ6QPdk0dc9cwTkVth267i05AxGoIu5IG +nLlxTWfKLudSaOlmlvj/ToOHCGxtqMkiOQ/r2zNOvm5A/SSzoxF5tW33kq9qTXvO +HC7OAGIlEWqUN38iiooOwX94LqTDQnQhJSAQgvLOnETY7L/G2RwWTNBNAVmSZQlo +ZHyB+eidQ2K1xPmqs7jygbI2Evgu+fy0HUkHP/pSR18E9Ed4NAn69F8T/FNBu1tx +Jiiq2L6T4cY34NWJSVTkzNeN1bKihkiw8xli7GsMAx/M13vXHVslmAf+t7Qmf5wU +EGiSxO/v9KrkJ0J70TxJ8aSuw2WpmeFD/Yvxg5RmAyvOksKd4qhPUDc1S4a1mIYw +UnpC3ToqTaFhQrC+C4V7aDD2Z2WSe1sUWEWxebTzpx7jO8Ewk6Wrc8GR/EkLEkxy +wB572tirOBouppxcUK/y2HyRfMMye550Ky8XSXnEf8BBEQCHSE8qRFNewY/ilZse +VpGw5vPPmG9LUEuFjNS+cjSacaT0/42O6V/31LKuKPmXw6rH1jo0QJbXRorX+9nD +LeC3Q0DhbExabeoz+Y20AlxvkVhOL6DlTqKPZA5iyBXBvFB/u5Bm//82FKJHiPjj +sFK2ZjwJ3yfYEsRZQYi45odzWfHA0Ca2NMsdjmRTk/N7AeaknX5KOFIvFqdZndOE +kg== +=rPGm +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build.xml b/build.xml index 9fa34a84e..d7b5482b4 100644 --- a/build.xml +++ b/build.xml @@ -47,8 +47,8 @@ under the License. The Apache POI project Ant build. - - + + @@ -56,7 +56,7 @@ under the License. - + @@ -82,7 +82,11 @@ under the License. - + + + @@ -175,8 +179,8 @@ under the License. value="${repository.m2}/maven2/org/apache/xmlbeans/xmlbeans/2.6.0/xmlbeans-2.6.0.jar"/> - - + + @@ -194,14 +198,14 @@ under the License. - - - - - - - - + + + + + + + + - - + + + - + @@ -281,7 +286,7 @@ under the License. - + @@ -289,14 +294,14 @@ under the License. - + - + @@ -331,7 +336,7 @@ under the License. - + @@ -360,6 +365,8 @@ under the License. - compile Compile all files from main, ooxml and scratchpad - test Run all unit tests from main, ooxml and scratchpad - jar Produce jar files + - jar-src Produce source-jar files + - assemble Produce the zipped distribution files - site Generate all documentation (Requires Apache Forrest) - dist Create a distribution (Requires Apache Forrest) @@ -409,6 +416,7 @@ under the License. + @@ -417,9 +425,13 @@ under the License. + + + + @@ -721,7 +733,7 @@ under the License. - + @@ -976,7 +988,7 @@ under the License. - + @@ -1280,7 +1292,7 @@ under the License. description="Generates the API documentation"> @@ -1440,7 +1452,7 @@ under the License. - + @@ -1508,12 +1520,12 @@ under the License. - + @@ -1628,6 +1640,14 @@ under the License. Use ${dist.dir}/multisign.sh to create md5 checksums and GPG signatures + + + + + + + + @@ -1744,7 +1764,30 @@ under the License. - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doap_POI.rdf b/doap_POI.rdf index e0123c2a8..17dee9ff6 100644 --- a/doap_POI.rdf +++ b/doap_POI.rdf @@ -19,22 +19,56 @@ Java + + + Apache POI 3.12 + 2015-05-11 + 3.12 + + + + + Apache POI 3.11 + 2014-12-21 + 3.11 + + + + + Apache POI 3.10.1 + 2014-08-18 + 3.10.1 + + + + + Apache POI 3.10 + 2014-02-08 + 3.10 + + Apache POI 3.9 2012-12-03 3.9 + + Apache POI 3.8 2012-03-26 3.8 + + Apache POI 3.7 2010-10-29 3.7 + + Apache POI 3.6 2009-12-14 diff --git a/legal/NOTICE b/legal/NOTICE index e5aa5f5a7..be2eae70d 100644 --- a/legal/NOTICE +++ b/legal/NOTICE @@ -1,5 +1,5 @@ Apache POI -Copyright 2003-2014 The Apache Software Foundation +Copyright 2003-2015 The Apache Software Foundation This product includes software developed by The Apache Software Foundation (http://www.apache.org/). diff --git a/osgi/pom.xml b/osgi/pom.xml new file mode 100644 index 000000000..2849467a9 --- /dev/null +++ b/osgi/pom.xml @@ -0,0 +1,229 @@ + + + + + 4.0.0 + + + org.apache + apache + 10 + + + + org.apache.poi + poi-bundle + bundle + Apache POI OSGi bundle + + OSGi bundle that contains Apache POI, and the dependencies. + + http://poi.apache.org/ + ${poi.version} + + + + 1.6 + 1.6 + 4.4.0 + + + + + ${project.groupId} + poi + ${poi.version} + + + ${project.groupId} + poi-scratchpad + ${poi.version} + + + ${project.groupId} + poi-ooxml + ${poi.version} + + + + + junit + junit + 4.12 + + + org.ops4j.pax.exam + pax-exam-junit4 + ${pax.exam.version} + test + + + org.ops4j.pax.exam + pax-exam-container-native + ${pax.exam.version} + test + + + org.apache.felix + org.apache.felix.framework + 4.6.0 + test + + + org.ops4j.pax.exam + pax-exam-link-assembly + ${pax.exam.version} + test + + + org.ops4j.pax.url + pax-url-aether + 2.3.0 + test + + + javax.inject + javax.inject + 1 + test + + + org.osgi + org.osgi.core + 5.0.0 + provided + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + org.apache.poi.osgi.Activator + + + poi;inline=true, + poi-scratchpad;inline=true, + poi-ooxml;inline=true, + poi-ooxml-schemas, + xmlbeans + + true + ${project.url} + + org.apache.poi.* + + + !org.junit, + *, + org.apache.xmlbeans.impl.xpath.saxon;resolution:=optional, + org.apache.xmlbeans.impl.xquery.saxon;resolution:=optional, + org.bouncycastle.cert;resolution:=optional, + org.bouncycastle.cert.ocsp;resolution:=optional, + org.bouncycastle.cms.bc;resolution:=optional, + org.bouncycastle.cert.jcajce;resolution:=optional, + org.bouncycastle.operator;resolution:=optional, + org.bouncycastle.operator.bc;resolution:=optional, + org.bouncycastle.tsp;resolution:=optional, + org.openxmlformats.schemas.officeDocument.x2006.math;resolution:=optional, + org.openxmlformats.schemas.schemaLibrary.x2006.main;resolution:=optional, + schemasMicrosoftComOfficePowerpoint;resolution:=optional, + schemasMicrosoftComOfficeWord;resolution:=optional, + + + + + + maven-compiler-plugin + 3.2 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + + java6 + + [1.6,) + + + + + maven-assembly-plugin + + + pre-integration-test + + single + + + test-bundles.xml + test + false + + + + + + maven-failsafe-plugin + 2.10 + + + + integration-test + verify + + + + + + + WARN + + + + + + + + + + + The Apache Software Founation + http://www.apache.org + + + http://svn.apache.org/viewvc/poi/trunk/osgi + scm:svn:http://svn.apache.org/repos/asf/poi/trunk/osgi + scm:svn:https://svn.apache.org/repos/asf/poi/trunk/osgi + + diff --git a/osgi/src/main/java/org/apache/poi/osgi/Activator.java b/osgi/src/main/java/org/apache/poi/osgi/Activator.java new file mode 100644 index 000000000..2f0212bd4 --- /dev/null +++ b/osgi/src/main/java/org/apache/poi/osgi/Activator.java @@ -0,0 +1,28 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.osgi; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + public void start(BundleContext context) throws Exception { + } + public void stop(BundleContext context) throws Exception { + } +} diff --git a/osgi/src/test/java/org/apache/poi/osgi/TestOSGiBundle.java b/osgi/src/test/java/org/apache/poi/osgi/TestOSGiBundle.java new file mode 100644 index 000000000..738d96b99 --- /dev/null +++ b/osgi/src/test/java/org/apache/poi/osgi/TestOSGiBundle.java @@ -0,0 +1,84 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.osgi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.ops4j.pax.exam.CoreOptions.bundle; +import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.options; + +import javax.inject.Inject; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; + +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerMethod; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; + +/** + * Test to ensure that all our main formats can create, write + * and read back in, when running under OSGi + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerMethod.class) +public class TestOSGiBundle { + + private final File TARGET = new File("target"); + + @Inject + private BundleContext bc; + + @Configuration + public Option[] configuration() throws IOException, URISyntaxException { + File base = new File(TARGET, "test-bundles"); + return options( + junitBundles(), + bundle(new File(base, "poi-bundle.jar").toURI().toURL().toString())); + } + + @Test + public void testHSSF() throws Exception { + HSSFWorkbook wb = new HSSFWorkbook(); + HSSFSheet s = wb.createSheet("OSGi"); + s.createRow(0).createCell(0).setCellValue("With OSGi"); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + wb.write(baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + wb = new HSSFWorkbook(bais); + assertEquals(1, wb.getNumberOfSheets()); + + s = wb.getSheet("OSGi"); + assertEquals("With OSGi", s.getRow(0).getCell(0).toString()); + } +} diff --git a/osgi/test-bundles.xml b/osgi/test-bundles.xml new file mode 100644 index 000000000..11502761e --- /dev/null +++ b/osgi/test-bundles.xml @@ -0,0 +1,34 @@ + + + bundles + + dir + + false + + + + ${artifact.artifactId}.jar + + org.apache.poi:poi-bundle + + + + diff --git a/src/examples/src/org/apache/poi/hpsf/examples/ReadCustomPropertySets.java b/src/examples/src/org/apache/poi/hpsf/examples/ReadCustomPropertySets.java index bf6bcd1f8..8d1a0a9c8 100644 --- a/src/examples/src/org/apache/poi/hpsf/examples/ReadCustomPropertySets.java +++ b/src/examples/src/org/apache/poi/hpsf/examples/ReadCustomPropertySets.java @@ -93,12 +93,12 @@ public class ReadCustomPropertySets out(" No. of sections: " + sectionCount); /* Print the list of sections: */ - List sections = ps.getSections(); + List
sections = ps.getSections(); int nr = 0; - for (Iterator i = sections.iterator(); i.hasNext();) + for (Iterator
i = sections.iterator(); i.hasNext();) { /* Print a single section: */ - Section sec = (Section) i.next(); + Section sec = i.next(); out(" Section " + nr++ + ":"); String s = hex(sec.getFormatID().getBytes()); s = s.substring(0, s.length() - 1); diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/CreateCells.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/CreateCells.java index ff8a0b73c..d2141b050 100644 --- a/src/examples/src/org/apache/poi/hssf/usermodel/examples/CreateCells.java +++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/CreateCells.java @@ -50,5 +50,7 @@ public class CreateCells { FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close(); + + wb.close(); } } diff --git a/src/examples/src/org/apache/poi/ss/examples/ConditionalFormats.java b/src/examples/src/org/apache/poi/ss/examples/ConditionalFormats.java index d0ce7674e..dd1398b86 100644 --- a/src/examples/src/org/apache/poi/ss/examples/ConditionalFormats.java +++ b/src/examples/src/org/apache/poi/ss/examples/ConditionalFormats.java @@ -21,6 +21,8 @@ package org.apache.poi.ss.examples; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbook; @@ -31,10 +33,9 @@ import java.io.IOException; * Excel Conditional Formatting -- Examples * *

- * Based on the code snippets from http://www.contextures.com/xlcondformat03.html + * Partly based on the code snippets from + * http://www.contextures.com/xlcondformat03.html *

- * - * @author Yegor Kozlov */ public class ConditionalFormats { @@ -46,6 +47,7 @@ public class ConditionalFormats { sameCell(wb.createSheet("Same Cell")); multiCell(wb.createSheet("MultiCell")); + overlapping(wb.createSheet("Overlapping")); errors(wb.createSheet("Errors")); hideDupplicates(wb.createSheet("Hide Dups")); formatDuplicates(wb.createSheet("Duplicates")); @@ -53,6 +55,9 @@ public class ConditionalFormats { expiry(wb.createSheet("Expiry")); shadeAlt(wb.createSheet("Shade Alt")); shadeBands(wb.createSheet("Shade Bands")); + iconSets(wb.createSheet("Icon Sets")); + + // TODO Add colour scales, data bars etc, see bug #58130 // Write the output to a file String file = "cf-poi.xls"; @@ -60,7 +65,7 @@ public class ConditionalFormats { FileOutputStream out = new FileOutputStream(file); wb.write(out); out.close(); - + System.out.println("Generated: " + file); } /** @@ -139,6 +144,71 @@ public class ConditionalFormats { sheet.getRow(2).createCell(4).setCellValue("<== Condition 1: Formula Is =$B2>75 (Blue Fill)"); } + + /** + * Multiple conditional formatting rules can apply to + * one cell, some combining, some beating others. + * Done in order of the rules added to the + * SheetConditionalFormatting object + */ + static void overlapping(Sheet sheet) { + for (int i=0; i<40; i++) { + int rn = i+1; + Row r = sheet.createRow(i); + r.createCell(0).setCellValue("This is row " + rn + " (" + i + ")"); + String str = ""; + if (rn%2 == 0) str = str + "even "; + if (rn%3 == 0) str = str + "x3 "; + if (rn%5 == 0) str = str + "x5 "; + if (rn%10 == 0) str = str + "x10 "; + if (str.length() == 0) str = "nothing special..."; + r.createCell(1).setCellValue("It is " + str); + } + sheet.autoSizeColumn(0); + sheet.autoSizeColumn(1); + + sheet.getRow(1).createCell(3).setCellValue("Even rows are blue"); + sheet.getRow(2).createCell(3).setCellValue("Multiples of 3 have a grey background"); + sheet.getRow(4).createCell(3).setCellValue("Multiples of 5 are bold"); + sheet.getRow(9).createCell(3).setCellValue("Multiples of 10 are red (beats even)"); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + // Condition 1: Row divides by 10, red (will beat #1) + ConditionalFormattingRule rule1 = + sheetCF.createConditionalFormattingRule("MOD(ROW(),10)=0"); + FontFormatting font1 = rule1.createFontFormatting(); + font1.setFontColorIndex(IndexedColors.RED.index); + + // Condition 2: Row is even, blue + ConditionalFormattingRule rule2 = + sheetCF.createConditionalFormattingRule("MOD(ROW(),2)=0"); + FontFormatting font2 = rule2.createFontFormatting(); + font2.setFontColorIndex(IndexedColors.BLUE.index); + + // Condition 3: Row divides by 5, bold + ConditionalFormattingRule rule3 = + sheetCF.createConditionalFormattingRule("MOD(ROW(),5)=0"); + FontFormatting font3 = rule3.createFontFormatting(); + font3.setFontStyle(false, true); + + // Condition 4: Row divides by 3, grey background + ConditionalFormattingRule rule4 = + sheetCF.createConditionalFormattingRule("MOD(ROW(),3)=0"); + PatternFormatting fill4 = rule4.createPatternFormatting(); + fill4.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.index); + fill4.setFillPattern(PatternFormatting.SOLID_FOREGROUND); + + // Apply + CellRangeAddress[] regions = { + CellRangeAddress.valueOf("A1:F41") + }; + + sheetCF.addConditionalFormatting(regions, rule1); + sheetCF.addConditionalFormatting(regions, rule2); + sheetCF.addConditionalFormatting(regions, rule3); + sheetCF.addConditionalFormatting(regions, rule4); + } /** * Use Excel conditional formatting to check for errors, @@ -346,4 +416,64 @@ public class ConditionalFormats { sheet.createRow(0).createCell(1).setCellValue("Shade Bands of Rows"); sheet.createRow(1).createCell(1).setCellValue("Condition: Formula Is =MOD(ROW(),6)<2 (Light Grey Fill)"); } + + /** + * Icon Sets / Multi-States allow you to have icons shown which vary + * based on the values, eg Red traffic light / Yellow traffic light / + * Green traffic light + */ + static void iconSets(Sheet sheet) { + sheet.createRow(0).createCell(0).setCellValue("Icon Sets"); + Row r = sheet.createRow(1); + r.createCell(0).setCellValue("Reds"); + r.createCell(1).setCellValue(0); + r.createCell(2).setCellValue(0); + r.createCell(3).setCellValue(0); + r = sheet.createRow(2); + r.createCell(0).setCellValue("Yellows"); + r.createCell(1).setCellValue(5); + r.createCell(2).setCellValue(5); + r.createCell(3).setCellValue(5); + r = sheet.createRow(3); + r.createCell(0).setCellValue("Greens"); + r.createCell(1).setCellValue(10); + r.createCell(2).setCellValue(10); + r.createCell(3).setCellValue(10); + + SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting(); + + CellRangeAddress[] regions = { CellRangeAddress.valueOf("B1:B4") }; + ConditionalFormattingRule rule1 = + sheetCF.createConditionalFormattingRule(IconSet.GYR_3_TRAFFIC_LIGHTS); + IconMultiStateFormatting im1 = rule1.getMultiStateFormatting(); + im1.getThresholds()[0].setRangeType(RangeType.MIN); + im1.getThresholds()[1].setRangeType(RangeType.PERCENT); + im1.getThresholds()[1].setValue(33d); + im1.getThresholds()[2].setRangeType(RangeType.MAX); + sheetCF.addConditionalFormatting(regions, rule1); + + regions = new CellRangeAddress[] { CellRangeAddress.valueOf("C1:C4") }; + ConditionalFormattingRule rule2 = + sheetCF.createConditionalFormattingRule(IconSet.GYR_3_FLAGS); + IconMultiStateFormatting im2 = rule1.getMultiStateFormatting(); + im2.getThresholds()[0].setRangeType(RangeType.PERCENT); + im2.getThresholds()[0].setValue(0d); + im2.getThresholds()[1].setRangeType(RangeType.PERCENT); + im2.getThresholds()[1].setValue(33d); + im2.getThresholds()[2].setRangeType(RangeType.PERCENT); + im2.getThresholds()[2].setValue(67d); + sheetCF.addConditionalFormatting(regions, rule2); + + regions = new CellRangeAddress[] { CellRangeAddress.valueOf("D1:D4") }; + ConditionalFormattingRule rule3 = + sheetCF.createConditionalFormattingRule(IconSet.GYR_3_SYMBOLS_CIRCLE); + IconMultiStateFormatting im3 = rule1.getMultiStateFormatting(); + im3.setIconOnly(true); + im3.getThresholds()[0].setRangeType(RangeType.MIN); + im3.getThresholds()[1].setRangeType(RangeType.NUMBER); + im3.getThresholds()[1].setValue(3d); + im3.getThresholds()[2].setRangeType(RangeType.NUMBER); + im3.getThresholds()[2].setValue(7d); + sheetCF.addConditionalFormatting(regions, rule3); + } } diff --git a/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java b/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java index b5480cf59..bcfb5dffe 100644 --- a/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java +++ b/src/examples/src/org/apache/poi/ss/examples/html/ToHtml.java @@ -289,7 +289,7 @@ public class ToHtml { private void fontStyle(CellStyle style) { Font font = wb.getFontAt(style.getFontIndex()); - if (font.getBoldweight() >= HSSFFont.BOLDWEIGHT_NORMAL) + if (font.getBoldweight() >= HSSFFont.BOLDWEIGHT_BOLD) out.format(" font-weight: bold;%n"); if (font.getItalic()) out.format(" font-style: italic;%n"); @@ -309,8 +309,12 @@ public class ToHtml { style = wb.getCellStyleAt((short) 0); StringBuilder sb = new StringBuilder(); Formatter fmt = new Formatter(sb); - fmt.format("style_%02x", style.getIndex()); - return fmt.toString(); + try { + fmt.format("style_%02x", style.getIndex()); + return fmt.toString(); + } finally { + fmt.close(); + } } private void styleOut(String attr, K key, Map mapping) { diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/AligningCells.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/AligningCells.java index 6ed76081b..aa96056e4 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/AligningCells.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/AligningCells.java @@ -114,16 +114,17 @@ public class AligningCells { // Make the selection CTRowImpl ctRow = (CTRowImpl) row.getCTRow(); - List spanList = new ArrayList(); // Add object with format start_coll:end_coll. For example 1:3 will span from // cell 1 to cell 3, where the column index starts with 0 // // You can add multiple spans for one row Object span = start_column + ":" + end_column; + + List spanList = new ArrayList(); spanList.add(span); //add spns to the row ctRow.setSpans(spanList); } -} \ No newline at end of file +} diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java index 00c534274..d9928151a 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java @@ -23,6 +23,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; +import org.apache.poi.openxml4j.opc.internal.ZipHelper; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.util.CellReference; @@ -165,27 +166,31 @@ public class BigGridDemo { * @param out the stream to write the result to */ private static void substitute(File zipfile, File tmpfile, String entry, OutputStream out) throws IOException { - ZipFile zip = new ZipFile(zipfile); + ZipFile zip = ZipHelper.openZipFile(zipfile); - ZipOutputStream zos = new ZipOutputStream(out); + try { + ZipOutputStream zos = new ZipOutputStream(out); - @SuppressWarnings("unchecked") - Enumeration en = (Enumeration) zip.entries(); - while (en.hasMoreElements()) { - ZipEntry ze = en.nextElement(); - if(!ze.getName().equals(entry)){ - zos.putNextEntry(new ZipEntry(ze.getName())); - InputStream is = zip.getInputStream(ze); - copyStream(is, zos); - is.close(); + @SuppressWarnings("unchecked") + Enumeration en = (Enumeration) zip.entries(); + while (en.hasMoreElements()) { + ZipEntry ze = en.nextElement(); + if(!ze.getName().equals(entry)){ + zos.putNextEntry(new ZipEntry(ze.getName())); + InputStream is = zip.getInputStream(ze); + copyStream(is, zos); + is.close(); + } } + zos.putNextEntry(new ZipEntry(entry)); + InputStream is = new FileInputStream(tmpfile); + copyStream(is, zos); + is.close(); + + zos.close(); + } finally { + zip.close(); } - zos.putNextEntry(new ZipEntry(entry)); - InputStream is = new FileInputStream(tmpfile); - copyStream(is, zos); - is.close(); - - zos.close(); } private static void copyStream(InputStream in, OutputStream out) throws IOException { diff --git a/src/integrationtest/build.xml b/src/integrationtest/build.xml new file mode 100644 index 000000000..795788e44 --- /dev/null +++ b/src/integrationtest/build.xml @@ -0,0 +1,145 @@ + + + + + Test-Ant file which verifies that the Apache POI distribution build sources can be compiled successfully. + + Before running this, you should execute the "assemble" target in the main build.xml to have the packaged files + created correctly. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/integrationtest/org/apache/poi/TestAllFiles.java b/src/integrationtest/org/apache/poi/TestAllFiles.java index 460830353..85b058084 100644 --- a/src/integrationtest/org/apache/poi/TestAllFiles.java +++ b/src/integrationtest/org/apache/poi/TestAllFiles.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.poi.hwpf.OldWordFileFormatException; import org.apache.poi.stress.*; import org.apache.tools.ant.DirectoryScanner; import org.junit.Test; @@ -65,83 +66,91 @@ import org.junit.runners.Parameterized.Parameters; */ @RunWith(Parameterized.class) public class TestAllFiles { - private static final File ROOT_DIR = new File("test-data"); + private static final File ROOT_DIR = new File("test-data"); // map file extensions to the actual mappers - private static final Map HANDLERS = new HashMap(); - static { - // Excel - HANDLERS.put(".xls", new HSSFFileHandler()); - HANDLERS.put(".xlsx", new XSSFFileHandler()); - HANDLERS.put(".xlsm", new XSSFFileHandler()); - HANDLERS.put(".xltx", new XSSFFileHandler()); - HANDLERS.put(".xlsb", new XSSFFileHandler()); - - // Word - HANDLERS.put(".doc", new HWPFFileHandler()); - HANDLERS.put(".docx", new XWPFFileHandler()); - HANDLERS.put(".dotx", new XWPFFileHandler()); - HANDLERS.put(".docm", new XWPFFileHandler()); - HANDLERS.put(".ooxml", new XWPFFileHandler()); // OPCPackage + private static final Map HANDLERS = new HashMap(); + static { + // Excel + HANDLERS.put(".xls", new HSSFFileHandler()); + HANDLERS.put(".xlsx", new XSSFFileHandler()); + HANDLERS.put(".xlsm", new XSSFFileHandler()); + HANDLERS.put(".xltx", new XSSFFileHandler()); + HANDLERS.put(".xlsb", new XSSFFileHandler()); - // Powerpoint - HANDLERS.put(".ppt", new HSLFFileHandler()); - HANDLERS.put(".pptx", new XSLFFileHandler()); - HANDLERS.put(".pptm", new XSLFFileHandler()); - HANDLERS.put(".ppsm", new XSLFFileHandler()); - HANDLERS.put(".ppsx", new XSLFFileHandler()); - HANDLERS.put(".thmx", new XSLFFileHandler()); + // Word + HANDLERS.put(".doc", new HWPFFileHandler()); + HANDLERS.put(".docx", new XWPFFileHandler()); + HANDLERS.put(".dotx", new XWPFFileHandler()); + HANDLERS.put(".docm", new XWPFFileHandler()); + HANDLERS.put(".ooxml", new XWPFFileHandler()); // OPCPackage - // Outlook - HANDLERS.put(".msg", new HSMFFileHandler()); - - // Publisher - HANDLERS.put(".pub", new HPBFFileHandler()); + // Powerpoint + HANDLERS.put(".ppt", new HSLFFileHandler()); + HANDLERS.put(".pptx", new XSLFFileHandler()); + HANDLERS.put(".pptm", new XSLFFileHandler()); + HANDLERS.put(".ppsm", new XSLFFileHandler()); + HANDLERS.put(".ppsx", new XSLFFileHandler()); + HANDLERS.put(".thmx", new XSLFFileHandler()); - // Visio - HANDLERS.put(".vsd", new HDGFFileHandler()); - - // POIFS - HANDLERS.put(".ole2", new POIFSFileHandler()); + // Outlook + HANDLERS.put(".msg", new HSMFFileHandler()); - // Microsoft Admin Template? - HANDLERS.put(".adm", new HPSFFileHandler()); + // Publisher + HANDLERS.put(".pub", new HPBFFileHandler()); - // Microsoft TNEF - HANDLERS.put(".dat", new HMEFFileHandler()); - - // TODO: are these readable by some of the formats? - HANDLERS.put(".shw", new NullFileHandler()); - HANDLERS.put(".zvi", new NullFileHandler()); - HANDLERS.put(".mpp", new NullFileHandler()); - HANDLERS.put(".qwp", new NullFileHandler()); - HANDLERS.put(".wps", new NullFileHandler()); - HANDLERS.put(".bin", new NullFileHandler()); - HANDLERS.put(".xps", new NullFileHandler()); - HANDLERS.put(".sldprt", new NullFileHandler()); - HANDLERS.put(".mdb", new NullFileHandler()); - HANDLERS.put(".vml", new NullFileHandler()); + // Visio - binary + HANDLERS.put(".vsd", new HDGFFileHandler()); + + // Visio - ooxml (currently unsupported) + HANDLERS.put(".vsdm", new NullFileHandler()); + HANDLERS.put(".vsdx", new NullFileHandler()); + HANDLERS.put(".vssm", new NullFileHandler()); + HANDLERS.put(".vssx", new NullFileHandler()); + HANDLERS.put(".vstm", new NullFileHandler()); + HANDLERS.put(".vstx", new NullFileHandler()); - // ignore some file types, images, other formats, ... - HANDLERS.put(".txt", new NullFileHandler()); - HANDLERS.put(".pdf", new NullFileHandler()); - HANDLERS.put(".rtf", new NullFileHandler()); - HANDLERS.put(".gif", new NullFileHandler()); - HANDLERS.put(".html", new NullFileHandler()); - HANDLERS.put(".png", new NullFileHandler()); - HANDLERS.put(".wmf", new NullFileHandler()); - HANDLERS.put(".emf", new NullFileHandler()); - HANDLERS.put(".dib", new NullFileHandler()); - HANDLERS.put(".svg", new NullFileHandler()); - HANDLERS.put(".pict", new NullFileHandler()); - HANDLERS.put(".jpg", new NullFileHandler()); - HANDLERS.put(".wav", new NullFileHandler()); - HANDLERS.put(".pfx", new NullFileHandler()); - HANDLERS.put(".xml", new NullFileHandler()); - HANDLERS.put(".csv", new NullFileHandler()); - - // map some files without extension - HANDLERS.put("spreadsheet/BigSSTRecord", new NullFileHandler()); + // POIFS + HANDLERS.put(".ole2", new POIFSFileHandler()); + + // Microsoft Admin Template? + HANDLERS.put(".adm", new HPSFFileHandler()); + + // Microsoft TNEF + HANDLERS.put(".dat", new HMEFFileHandler()); + + // TODO: are these readable by some of the formats? + HANDLERS.put(".shw", new NullFileHandler()); + HANDLERS.put(".zvi", new NullFileHandler()); + HANDLERS.put(".mpp", new NullFileHandler()); + HANDLERS.put(".qwp", new NullFileHandler()); + HANDLERS.put(".wps", new NullFileHandler()); + HANDLERS.put(".bin", new NullFileHandler()); + HANDLERS.put(".xps", new NullFileHandler()); + HANDLERS.put(".sldprt", new NullFileHandler()); + HANDLERS.put(".mdb", new NullFileHandler()); + HANDLERS.put(".vml", new NullFileHandler()); + + // ignore some file types, images, other formats, ... + HANDLERS.put(".txt", new NullFileHandler()); + HANDLERS.put(".pdf", new NullFileHandler()); + HANDLERS.put(".rtf", new NullFileHandler()); + HANDLERS.put(".gif", new NullFileHandler()); + HANDLERS.put(".html", new NullFileHandler()); + HANDLERS.put(".png", new NullFileHandler()); + HANDLERS.put(".wmf", new NullFileHandler()); + HANDLERS.put(".emf", new NullFileHandler()); + HANDLERS.put(".dib", new NullFileHandler()); + HANDLERS.put(".svg", new NullFileHandler()); + HANDLERS.put(".pict", new NullFileHandler()); + HANDLERS.put(".jpg", new NullFileHandler()); + HANDLERS.put(".wav", new NullFileHandler()); + HANDLERS.put(".pfx", new NullFileHandler()); + HANDLERS.put(".xml", new NullFileHandler()); + HANDLERS.put(".csv", new NullFileHandler()); + + // map some files without extension + HANDLERS.put("spreadsheet/BigSSTRecord", new NullFileHandler()); HANDLERS.put("spreadsheet/BigSSTRecord2", new NullFileHandler()); HANDLERS.put("spreadsheet/BigSSTRecord2CR1", new NullFileHandler()); HANDLERS.put("spreadsheet/BigSSTRecord2CR2", new NullFileHandler()); @@ -151,88 +160,104 @@ public class TestAllFiles { HANDLERS.put("spreadsheet/BigSSTRecord2CR6", new NullFileHandler()); HANDLERS.put("spreadsheet/BigSSTRecord2CR7", new NullFileHandler()); HANDLERS.put("spreadsheet/BigSSTRecordCR", new NullFileHandler()); - HANDLERS.put("spreadsheet/test_properties1", new NullFileHandler()); - } + HANDLERS.put("spreadsheet/test_properties1", new NullFileHandler()); + } - private static final Set EXPECTED_FAILURES = new HashSet(); - static { - // password protected files - EXPECTED_FAILURES.add("spreadsheet/password.xls"); - EXPECTED_FAILURES.add("spreadsheet/51832.xls"); - EXPECTED_FAILURES.add("document/PasswordProtected.doc"); - EXPECTED_FAILURES.add("slideshow/Password_Protected-hello.ppt"); - EXPECTED_FAILURES.add("slideshow/Password_Protected-56-hello.ppt"); - EXPECTED_FAILURES.add("slideshow/Password_Protected-np-hello.ppt"); - EXPECTED_FAILURES.add("slideshow/cryptoapi-proc2356.ppt"); - //EXPECTED_FAILURES.add("document/bug53475-password-is-pass.docx"); - //EXPECTED_FAILURES.add("document/bug53475-password-is-solrcell.docx"); - EXPECTED_FAILURES.add("spreadsheet/xor-encryption-abc.xls"); + // Old Word Documents where we can at least extract some text + private static final Set OLD_FILES = new HashSet(); + static { + OLD_FILES.add("document/Bug49933.doc"); + OLD_FILES.add("document/Bug51944.doc"); + OLD_FILES.add("document/Word6.doc"); + OLD_FILES.add("document/Word6_sections.doc"); + OLD_FILES.add("document/Word6_sections2.doc"); + OLD_FILES.add("document/Word95.doc"); + OLD_FILES.add("document/word95err.doc"); + OLD_FILES.add("hpsf/TestMickey.doc"); + OLD_FILES.add("document/52117.doc"); + } + + private static final Set EXPECTED_FAILURES = new HashSet(); + static { + // password protected files + EXPECTED_FAILURES.add("spreadsheet/password.xls"); + EXPECTED_FAILURES.add("spreadsheet/protected_passtika.xlsx"); + EXPECTED_FAILURES.add("spreadsheet/51832.xls"); + EXPECTED_FAILURES.add("document/PasswordProtected.doc"); + EXPECTED_FAILURES.add("slideshow/Password_Protected-hello.ppt"); + EXPECTED_FAILURES.add("slideshow/Password_Protected-56-hello.ppt"); + EXPECTED_FAILURES.add("slideshow/Password_Protected-np-hello.ppt"); + EXPECTED_FAILURES.add("slideshow/cryptoapi-proc2356.ppt"); + //EXPECTED_FAILURES.add("document/bug53475-password-is-pass.docx"); + //EXPECTED_FAILURES.add("document/bug53475-password-is-solrcell.docx"); + EXPECTED_FAILURES.add("spreadsheet/xor-encryption-abc.xls"); EXPECTED_FAILURES.add("spreadsheet/35897-type4.xls"); //EXPECTED_FAILURES.add("poifs/protect.xlsx"); //EXPECTED_FAILURES.add("poifs/protected_sha512.xlsx"); //EXPECTED_FAILURES.add("poifs/extenxls_pwd123.xlsx"); //EXPECTED_FAILURES.add("poifs/protected_agile.docx"); - - // TODO: fails XMLExportTest, is this ok? - EXPECTED_FAILURES.add("spreadsheet/CustomXMLMapping-singleattributenamespace.xlsx"); - EXPECTED_FAILURES.add("spreadsheet/55864.xlsx"); - - // TODO: these fail now with some NPE/file read error because we now try to compute every value via Cell.toString()! - EXPECTED_FAILURES.add("spreadsheet/44958.xls"); - EXPECTED_FAILURES.add("spreadsheet/44958_1.xls"); - EXPECTED_FAILURES.add("spreadsheet/testArraysAndTables.xls"); - // TODO: good to ignore? - EXPECTED_FAILURES.add("spreadsheet/sample-beta.xlsx"); - EXPECTED_FAILURES.add("spreadsheet/49931.xls"); - EXPECTED_FAILURES.add("openxml4j/ContentTypeHasParameters.ooxml"); + // TODO: fails XMLExportTest, is this ok? + EXPECTED_FAILURES.add("spreadsheet/CustomXMLMapping-singleattributenamespace.xlsx"); + EXPECTED_FAILURES.add("spreadsheet/55864.xlsx"); - // This is actually a spreadsheet! - EXPECTED_FAILURES.add("hpsf/TestRobert_Flaherty.doc"); - - // some files that are broken, Excel 5.0/95, Word 95, ... - EXPECTED_FAILURES.add("spreadsheet/43493.xls"); - EXPECTED_FAILURES.add("spreadsheet/46904.xls"); - EXPECTED_FAILURES.add("document/56880.doc"); - EXPECTED_FAILURES.add("document/Bug49933.doc"); - EXPECTED_FAILURES.add("document/Bug50955.doc"); - EXPECTED_FAILURES.add("document/Bug51944.doc"); - EXPECTED_FAILURES.add("document/Word6.doc"); - EXPECTED_FAILURES.add("document/Word6_sections.doc"); - EXPECTED_FAILURES.add("document/Word6_sections2.doc"); - EXPECTED_FAILURES.add("document/Word95.doc"); - EXPECTED_FAILURES.add("document/word95err.doc"); - EXPECTED_FAILURES.add("hpsf/TestMickey.doc"); - EXPECTED_FAILURES.add("slideshow/PPT95.ppt"); - EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx"); - EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx"); - EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_NotPresentFAIL.docx"); - EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx"); - EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_OnlyOneCorePropertiesPartFAIL.docx"); - EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_UnauthorizedXMLLangAttributeFAIL.docx"); - EXPECTED_FAILURES.add("openxml4j/OPCCompliance_DerivedPartNameFAIL.docx"); - EXPECTED_FAILURES.add("spreadsheet/54764-2.xlsx"); // see TestXSSFBugs.bug54764() - EXPECTED_FAILURES.add("spreadsheet/54764.xlsx"); // see TestXSSFBugs.bug54764() + // TODO: these fail now with some NPE/file read error because we now try to compute every value via Cell.toString()! + EXPECTED_FAILURES.add("spreadsheet/44958.xls"); + EXPECTED_FAILURES.add("spreadsheet/44958_1.xls"); + EXPECTED_FAILURES.add("spreadsheet/testArraysAndTables.xls"); + + // TODO: good to ignore? + EXPECTED_FAILURES.add("spreadsheet/sample-beta.xlsx"); + EXPECTED_FAILURES.add("spreadsheet/49931.xls"); + EXPECTED_FAILURES.add("openxml4j/ContentTypeHasParameters.ooxml"); + + // This is actually a spreadsheet! + EXPECTED_FAILURES.add("hpsf/TestRobert_Flaherty.doc"); + + // some files that are broken, eg Word 95, ... + EXPECTED_FAILURES.add("spreadsheet/43493.xls"); + EXPECTED_FAILURES.add("spreadsheet/46904.xls"); + EXPECTED_FAILURES.add("document/56880.doc"); + EXPECTED_FAILURES.add("document/Bug50955.doc"); + EXPECTED_FAILURES.add("slideshow/PPT95.ppt"); + EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx"); + EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx"); + EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_NotPresentFAIL.docx"); + EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx"); + EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_OnlyOneCorePropertiesPartFAIL.docx"); + EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_UnauthorizedXMLLangAttributeFAIL.docx"); + EXPECTED_FAILURES.add("openxml4j/OPCCompliance_DerivedPartNameFAIL.docx"); + EXPECTED_FAILURES.add("spreadsheet/54764-2.xlsx"); // see TestXSSFBugs.bug54764() + EXPECTED_FAILURES.add("spreadsheet/54764.xlsx"); // see TestXSSFBugs.bug54764() EXPECTED_FAILURES.add("spreadsheet/Simple.xlsb"); + EXPECTED_FAILURES.add("poifs/unknown_properties.msg"); // POIFS properties corrupted + EXPECTED_FAILURES.add("poifs/only-zero-byte-streams.ole2"); // No actual contents + + // old Excel files, which we only support simple text extraction of EXPECTED_FAILURES.add("spreadsheet/testEXCEL_2.xls"); EXPECTED_FAILURES.add("spreadsheet/testEXCEL_3.xls"); EXPECTED_FAILURES.add("spreadsheet/testEXCEL_4.xls"); EXPECTED_FAILURES.add("spreadsheet/testEXCEL_5.xls"); EXPECTED_FAILURES.add("spreadsheet/testEXCEL_95.xls"); + + // OOXML Strict is not yet supported, see bug #57699 + EXPECTED_FAILURES.add("spreadsheet/SampleSS.strict.xlsx"); + EXPECTED_FAILURES.add("spreadsheet/SimpleStrict.xlsx"); + EXPECTED_FAILURES.add("spreadsheet/sample.strict.xlsx"); + + // non-TNEF files + EXPECTED_FAILURES.add("ddf/Container.dat"); + EXPECTED_FAILURES.add("ddf/47143.dat"); + } - // non-TNEF files - EXPECTED_FAILURES.add("ddf/Container.dat"); - EXPECTED_FAILURES.add("ddf/47143.dat"); - } - @Parameters(name="{index}: {0} using {1}") public static Iterable files() { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(ROOT_DIR); scanner.setExcludes(new String[] { "**/.svn/**" }); - + scanner.scan(); - + System.out.println("Handling " + scanner.getIncludedFiles().length + " files"); List files = new ArrayList(); @@ -240,47 +265,72 @@ public class TestAllFiles { file = file.replace('\\', '/'); // ... failures/handlers lookup doesn't work on windows otherwise files.add(new Object[] { file, HANDLERS.get(getExtension(file)) }); } - + return files; - } - + } + @Parameter(value=0) public String file; - + @Parameter(value=1) public FileHandler handler; - + @Test public void testAllFiles() throws Exception { - assertNotNull("Unknown file extension for file: " + file + ": " + getExtension(file), handler); - InputStream stream = new BufferedInputStream(new FileInputStream(new File(ROOT_DIR, file)),100); - try { - handler.handleFile(stream); - - assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!", - EXPECTED_FAILURES.contains(file)); - } catch (Exception e) { - // check if we expect failure for this file - if(!EXPECTED_FAILURES.contains(file)) { - throw new Exception("While handling " + file, e); - } - } finally { - stream.close(); - } - } + assertNotNull("Unknown file extension for file: " + file + ": " + getExtension(file), handler); + File inputFile = new File(ROOT_DIR, file); - private static String getExtension(String file) { - int pos = file.lastIndexOf('.'); - if(pos == -1 || pos == file.length()-1) { - return file; - } - - return file.substring(pos); - } + try { + InputStream stream = new BufferedInputStream(new FileInputStream(inputFile), 64*1024); + try { + handler.handleFile(stream); - private static class NullFileHandler implements FileHandler { - @Override + assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!", + OLD_FILES.contains(file)); + } finally { + stream.close(); + } + + handler.handleExtracting(inputFile); + + assertFalse("Expected to fail for file " + file + " and handler " + handler + ", but did not fail!", + EXPECTED_FAILURES.contains(file)); + } catch (OldWordFileFormatException e) { + // for old word files we should still support extracting text + if(OLD_FILES.contains(file)) { + handler.handleExtracting(inputFile); + } else { + // check if we expect failure for this file + if(!EXPECTED_FAILURES.contains(file) && !AbstractFileHandler.EXPECTED_EXTRACTOR_FAILURES.contains(file)) { + System.out.println("Failed: " + file); + throw new Exception("While handling " + file, e); + } + } + } catch (Exception e) { + // check if we expect failure for this file + if(!EXPECTED_FAILURES.contains(file) && !AbstractFileHandler.EXPECTED_EXTRACTOR_FAILURES.contains(file)) { + System.out.println("Failed: " + file); + throw new Exception("While handling " + file, e); + } + } + } + + private static String getExtension(String file) { + int pos = file.lastIndexOf('.'); + if(pos == -1 || pos == file.length()-1) { + return file; + } + + return file.substring(pos); + } + + private static class NullFileHandler implements FileHandler { + @Override public void handleFile(InputStream stream) throws Exception { - } - } + } + + @Override + public void handleExtracting(File file) throws Exception { + } + } } diff --git a/src/integrationtest/org/apache/poi/stress/AbstractFileHandler.java b/src/integrationtest/org/apache/poi/stress/AbstractFileHandler.java new file mode 100644 index 000000000..55e2c368f --- /dev/null +++ b/src/integrationtest/org/apache/poi/stress/AbstractFileHandler.java @@ -0,0 +1,143 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.stress; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashSet; +import java.util.Set; +import java.util.zip.ZipException; + +import org.apache.poi.POIOLE2TextExtractor; +import org.apache.poi.POITextExtractor; +import org.apache.poi.dev.OOXMLPrettyPrint; +import org.apache.poi.extractor.ExtractorFactory; +import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.xmlbeans.XmlException; + +public abstract class AbstractFileHandler implements FileHandler { + public static final Set EXPECTED_EXTRACTOR_FAILURES = new HashSet(); + static { + // password protected files + EXPECTED_EXTRACTOR_FAILURES.add("document/bug53475-password-is-pass.docx"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/extenxls_pwd123.xlsx"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/protect.xlsx"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/protected_agile.docx"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/protected_sha512.xlsx"); + + // unsupported file-types, no supported OLE2 parts + EXPECTED_EXTRACTOR_FAILURES.add("hmef/quick-winmail.dat"); + EXPECTED_EXTRACTOR_FAILURES.add("hmef/winmail-sample1.dat"); + EXPECTED_EXTRACTOR_FAILURES.add("hmef/bug52400-winmail-simple.dat"); + EXPECTED_EXTRACTOR_FAILURES.add("hmef/bug52400-winmail-with-attachments.dat"); + EXPECTED_EXTRACTOR_FAILURES.add("hpsf/Test0313rur.adm"); + EXPECTED_EXTRACTOR_FAILURES.add("hsmf/attachment_msg_pdf.msg"); + EXPECTED_EXTRACTOR_FAILURES.add("poifs/Notes.ole2"); + EXPECTED_EXTRACTOR_FAILURES.add("slideshow/testPPT.thmx"); + } + + public void handleExtracting(File file) throws Exception { + boolean before = ExtractorFactory.getThreadPrefersEventExtractors(); + try { + ExtractorFactory.setThreadPrefersEventExtractors(true); + handleExtractingInternal(file); + + ExtractorFactory.setThreadPrefersEventExtractors(false); + handleExtractingInternal(file); + } finally { + ExtractorFactory.setThreadPrefersEventExtractors(before); + } + + /* Did fail for some documents with special XML contents... + try { + OOXMLPrettyPrint.main(new String[] { file.getAbsolutePath(), + "/tmp/pretty-" + file.getName() }); + } catch (ZipException e) { + // ignore, not a Zip/OOXML file + }*/ + } + + private void handleExtractingInternal(File file) throws Exception { + long length = file.length(); + long modified = file.lastModified(); + + POITextExtractor extractor = ExtractorFactory.createExtractor(file); + try { + assertNotNull(extractor); + + assertNotNull(extractor.getText()); + + // also try metadata + POITextExtractor metadataExtractor = extractor.getMetadataTextExtractor(); + assertNotNull(metadataExtractor.getText()); + + assertFalse("Expected Extraction to fail for file " + file + " and handler " + this + ", but did not fail!", + EXPECTED_EXTRACTOR_FAILURES.contains(file)); + + assertEquals("File should not be modified by extractor", length, file.length()); + assertEquals("File should not be modified by extractor", modified, file.lastModified()); + + handleExtractingAsStream(file); + + if(extractor instanceof POIOLE2TextExtractor) { + HPSFPropertiesExtractor hpsfExtractor = new HPSFPropertiesExtractor((POIOLE2TextExtractor)extractor); + try { + assertNotNull(hpsfExtractor.getDocumentSummaryInformationText()); + assertNotNull(hpsfExtractor.getSummaryInformationText()); + String text = hpsfExtractor.getText(); + //System.out.println(text); + assertNotNull(text); + } finally { + hpsfExtractor.close(); + } + } + } catch (IllegalArgumentException e) { + if(!EXPECTED_EXTRACTOR_FAILURES.contains(file)) { + throw new Exception("While handling " + file, e); + } + } finally { + extractor.close(); + } + } + + private void handleExtractingAsStream(File file) throws FileNotFoundException, + IOException, InvalidFormatException, OpenXML4JException, + XmlException { + InputStream stream = new FileInputStream(file); + try { + POITextExtractor streamExtractor = ExtractorFactory.createExtractor(stream); + try { + assertNotNull(streamExtractor); + + assertNotNull(streamExtractor.getText()); + } finally { + streamExtractor.close(); + } + } finally { + stream.close(); + } + } +} diff --git a/src/integrationtest/org/apache/poi/stress/FileHandler.java b/src/integrationtest/org/apache/poi/stress/FileHandler.java index e6f3385f0..ce2991b0b 100644 --- a/src/integrationtest/org/apache/poi/stress/FileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/FileHandler.java @@ -16,6 +16,7 @@ ==================================================================== */ package org.apache.poi.stress; +import java.io.File; import java.io.InputStream; /** @@ -34,4 +35,10 @@ public interface FileHandler { * @throws Exception */ void handleFile(InputStream stream) throws Exception; + + /** + * Ensures that extracting text from the given file + * is returning some text. + */ + void handleExtracting(File file) throws Exception; } diff --git a/src/integrationtest/org/apache/poi/stress/HDGFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HDGFFileHandler.java index 7fac6647a..b9fe93a66 100644 --- a/src/integrationtest/org/apache/poi/stress/HDGFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HDGFFileHandler.java @@ -19,10 +19,12 @@ package org.apache.poi.stress; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import org.apache.poi.hdgf.HDGFDiagram; +import org.apache.poi.hdgf.extractor.VisioTextExtractor; import org.apache.poi.hdgf.streams.Stream; import org.apache.poi.hdgf.streams.TrailerStream; import org.apache.poi.poifs.filesystem.POIFSFileSystem; @@ -48,11 +50,27 @@ public class HDGFFileHandler extends POIFSFileHandler { // a test-case to test this locally without executing the full TestAllFiles @Test public void test() throws Exception { - InputStream stream = new FileInputStream("test-data/diagram/44501.vsd"); + File file = new File("test-data/diagram/44501.vsd"); + + InputStream stream = new FileInputStream(file); try { handleFile(stream); } finally { stream.close(); } + + handleExtracting(file); + + stream = new FileInputStream(file); + try { + VisioTextExtractor extractor = new VisioTextExtractor(stream); + try { + assertNotNull(extractor.getText()); + } finally { + extractor.close(); + } + } finally { + stream.close(); + } } } diff --git a/src/integrationtest/org/apache/poi/stress/HMEFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HMEFFileHandler.java index dfa875005..9f492bf0e 100644 --- a/src/integrationtest/org/apache/poi/stress/HMEFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HMEFFileHandler.java @@ -26,7 +26,7 @@ import org.apache.poi.hmef.attribute.MAPIAttribute; import org.apache.poi.hmef.attribute.MAPIStringAttribute; import org.junit.Test; -public class HMEFFileHandler implements FileHandler { +public class HMEFFileHandler extends AbstractFileHandler { @Override public void handleFile(InputStream stream) throws Exception { diff --git a/src/integrationtest/org/apache/poi/stress/HPBFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HPBFFileHandler.java index 31ad8bc12..a41b6ebad 100644 --- a/src/integrationtest/org/apache/poi/stress/HPBFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HPBFFileHandler.java @@ -18,10 +18,12 @@ package org.apache.poi.stress; import static org.junit.Assert.assertNotNull; +import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import org.apache.poi.hpbf.HPBFDocument; +import org.apache.poi.hpbf.extractor.PublisherTextExtractor; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.junit.Test; @@ -39,11 +41,28 @@ public class HPBFFileHandler extends POIFSFileHandler { // a test-case to test this locally without executing the full TestAllFiles @Test public void test() throws Exception { - InputStream stream = new FileInputStream("test-data/publisher/SampleBrochure.pub"); + File file = new File("test-data/publisher/SampleBrochure.pub"); + + InputStream stream = new FileInputStream(file); try { handleFile(stream); } finally { stream.close(); } + + handleExtracting(file); + + stream = new FileInputStream(file); + try { + PublisherTextExtractor extractor = new PublisherTextExtractor(stream); + try { + assertNotNull(extractor.getText()); + } finally { + extractor.close(); + } + } finally { + stream.close(); + } } + } diff --git a/src/integrationtest/org/apache/poi/stress/HPSFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HPSFFileHandler.java index b7d846ae6..6a53b2e00 100644 --- a/src/integrationtest/org/apache/poi/stress/HPSFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HPSFFileHandler.java @@ -18,6 +18,7 @@ package org.apache.poi.stress; import static org.junit.Assert.assertNotNull; +import java.io.File; import java.io.FileInputStream; import java.io.InputStream; @@ -25,7 +26,7 @@ import org.apache.poi.hpsf.HPSFPropertiesOnlyDocument; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.junit.Test; -public class HPSFFileHandler implements FileHandler { +public class HPSFFileHandler extends AbstractFileHandler { @Override public void handleFile(InputStream stream) throws Exception { HPSFPropertiesOnlyDocument hpsf = new HPSFPropertiesOnlyDocument(new POIFSFileSystem(stream)); @@ -43,4 +44,10 @@ public class HPSFFileHandler implements FileHandler { stream.close(); } } + + // a test-case to test this locally without executing the full TestAllFiles + @Test + public void testExtractor() throws Exception { + handleExtracting(new File("test-data/hpsf/TestBug44375.xls")); + } } diff --git a/src/integrationtest/org/apache/poi/stress/HSMFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HSMFFileHandler.java index 9de8b798c..d68504a04 100644 --- a/src/integrationtest/org/apache/poi/stress/HSMFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HSMFFileHandler.java @@ -22,6 +22,8 @@ import java.io.FileInputStream; import java.io.InputStream; import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.datatypes.AttachmentChunks; +import org.apache.poi.hsmf.datatypes.DirectoryChunk; import org.junit.Test; public class HSMFFileHandler extends POIFSFileHandler { @@ -32,6 +34,19 @@ public class HSMFFileHandler extends POIFSFileHandler { assertNotNull(mapi.getDisplayBCC()); assertNotNull(mapi.getMessageDate()); + AttachmentChunks[] attachments = mapi.getAttachmentFiles(); + + for(AttachmentChunks attachment : attachments) { + + DirectoryChunk chunkDirectory = attachment.attachmentDirectory; + if(chunkDirectory != null) { + MAPIMessage attachmentMSG = chunkDirectory.getAsEmbededMessage(); + assertNotNull(attachmentMSG); + String body = attachmentMSG.getTextBody(); + assertNotNull(body); + } + } + /* => Writing isn't yet supported... // write out the file File file = TempFile.createTempFile("StressTest", ".msg"); diff --git a/src/integrationtest/org/apache/poi/stress/HSSFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HSSFFileHandler.java index 19dbd97a0..dd579c4db 100644 --- a/src/integrationtest/org/apache/poi/stress/HSSFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HSSFFileHandler.java @@ -16,6 +16,7 @@ ==================================================================== */ package org.apache.poi.stress; +import java.io.File; import java.io.FileInputStream; import java.io.InputStream; @@ -49,4 +50,10 @@ public class HSSFFileHandler extends SpreadsheetHandler { stream.close(); } } + + // a test-case to test this locally without executing the full TestAllFiles + @Test + public void testExtractor() throws Exception { + handleExtracting(new File("test-data/spreadsheet/BOOK_in_capitals.xls")); + } } \ No newline at end of file diff --git a/src/integrationtest/org/apache/poi/stress/HWPFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HWPFFileHandler.java index 1b6d4646c..a56ddd2dc 100644 --- a/src/integrationtest/org/apache/poi/stress/HWPFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HWPFFileHandler.java @@ -18,12 +18,21 @@ package org.apache.poi.stress; import static org.junit.Assert.assertNotNull; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import org.apache.poi.hdf.extractor.WordDocument; import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.extractor.WordExtractor; import org.junit.Test; +@SuppressWarnings("deprecation") public class HWPFFileHandler extends POIFSFileHandler { @Override public void handleFile(InputStream stream) throws Exception { @@ -33,16 +42,57 @@ public class HWPFFileHandler extends POIFSFileHandler { assertNotNull(doc.getEndnotes()); handlePOIDocument(doc); + + // fails for many documents, but is deprecated anyway... + // handleWordDocument(doc); + } + + protected void handleWordDocument(HWPFDocument doc) throws IOException { + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + doc.write(outStream); + + WordDocument wordDoc = new WordDocument(new ByteArrayInputStream(outStream.toByteArray())); + + StringWriter docTextWriter = new StringWriter(); + PrintWriter out = new PrintWriter(docTextWriter); + try { + wordDoc.writeAllText(out); + } finally { + out.close(); + } + docTextWriter.close(); } // a test-case to test this locally without executing the full TestAllFiles @Test public void test() throws Exception { - InputStream stream = new FileInputStream("test-data/document/HeaderFooterUnicode.doc"); + File file = new File("test-data/document/52117.doc"); + + InputStream stream = new FileInputStream(file); try { handleFile(stream); } finally { stream.close(); } + + handleExtracting(file); + + stream = new FileInputStream(file); + try { + WordExtractor extractor = new WordExtractor(stream); + try { + assertNotNull(extractor.getText()); + } finally { + extractor.close(); + } + } finally { + stream.close(); + } } -} \ No newline at end of file + + @Test + public void testExtractingOld() throws Exception { + File file = new File("test-data/document/52117.doc"); + handleExtracting(file); + } +} diff --git a/src/integrationtest/org/apache/poi/stress/POIFSFileHandler.java b/src/integrationtest/org/apache/poi/stress/POIFSFileHandler.java index 31deac710..5c4a36e3c 100644 --- a/src/integrationtest/org/apache/poi/stress/POIFSFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/POIFSFileHandler.java @@ -25,7 +25,7 @@ import java.io.InputStream; import org.apache.poi.POIDocument; import org.apache.poi.poifs.filesystem.POIFSFileSystem; -public class POIFSFileHandler implements FileHandler { +public class POIFSFileHandler extends AbstractFileHandler { @Override public void handleFile(InputStream stream) throws Exception { diff --git a/src/integrationtest/org/apache/poi/stress/POIXMLDocumentHandler.java b/src/integrationtest/org/apache/poi/stress/POIXMLDocumentHandler.java index 103bb9be7..7b0821dcc 100644 --- a/src/integrationtest/org/apache/poi/stress/POIXMLDocumentHandler.java +++ b/src/integrationtest/org/apache/poi/stress/POIXMLDocumentHandler.java @@ -20,9 +20,17 @@ import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.io.InputStream; +import java.util.List; import org.apache.poi.POIXMLDocument; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.poifs.crypt.Decryptor; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.junit.Ignore; +import org.junit.Test; public final class POIXMLDocumentHandler { protected void handlePOIXMLDocument(POIXMLDocument doc) throws Exception { @@ -36,11 +44,33 @@ public final class POIXMLDocumentHandler { protected static boolean isEncrypted(InputStream stream) throws IOException { if (POIFSFileSystem.hasPOIFSHeader(stream)) { POIFSFileSystem poifs = new POIFSFileSystem(stream); - if (poifs.getRoot().hasEntry("EncryptedPackage")) { + if (poifs.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) { return true; } throw new IOException("wrong file format or file extension for OO XML file"); } return false; } + + // a test-case to test this locally without executing the full TestAllFiles + @Ignore("POIXMLDocument cannot handle this Visio file currently...") + @Test + public void test() throws Exception { + OPCPackage pkg = OPCPackage.open("test-data/diagram/test.vsdx", PackageAccess.READ); + try { + handlePOIXMLDocument(new TestPOIXMLDocument(pkg)); + } finally { + pkg.close(); + } + } + + private final static class TestPOIXMLDocument extends POIXMLDocument { + public TestPOIXMLDocument(OPCPackage pkg) { + super(pkg); + } + + public List getAllEmbedds() throws OpenXML4JException { + return null; + } + } } diff --git a/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java b/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java index aad703ce9..f12bbd2de 100644 --- a/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java +++ b/src/integrationtest/org/apache/poi/stress/SpreadsheetHandler.java @@ -30,7 +30,7 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; -public abstract class SpreadsheetHandler implements FileHandler { +public abstract class SpreadsheetHandler extends AbstractFileHandler { public void handleWorkbook(Workbook wb, String extension) throws IOException { // try to access some of the content readContent(wb); diff --git a/src/integrationtest/org/apache/poi/stress/XSLFFileHandler.java b/src/integrationtest/org/apache/poi/stress/XSLFFileHandler.java index 3464218fd..2669238be 100644 --- a/src/integrationtest/org/apache/poi/stress/XSLFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/XSLFFileHandler.java @@ -18,35 +18,97 @@ package org.apache.poi.stress; import static org.junit.Assert.assertNotNull; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.sl.draw.DrawFactory; +import org.apache.poi.sl.draw.Drawable; import org.apache.poi.xslf.XSLFSlideShow; +import org.apache.poi.xslf.usermodel.XMLSlideShow; +import org.apache.poi.xslf.usermodel.XSLFNotes; +import org.apache.poi.xslf.usermodel.XSLFShape; +import org.apache.poi.xslf.usermodel.XSLFSlide; +import org.apache.poi.xslf.usermodel.XSLFTextParagraph; +import org.apache.poi.xslf.usermodel.XSLFTextShape; import org.junit.Test; -public class XSLFFileHandler implements FileHandler { +public class XSLFFileHandler extends AbstractFileHandler { @Override public void handleFile(InputStream stream) throws Exception { - // ignore password protected files - if (POIXMLDocumentHandler.isEncrypted(stream)) return; - XSLFSlideShow slide = new XSLFSlideShow(OPCPackage.open(stream)); assertNotNull(slide.getPresentation()); assertNotNull(slide.getSlideMasterReferences()); assertNotNull(slide.getSlideReferences()); new POIXMLDocumentHandler().handlePOIXMLDocument(slide); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + slide.write(out); + } finally { + out.close(); + } + + createBitmaps(out); } + private void createBitmaps(ByteArrayOutputStream out) throws IOException { + XMLSlideShow ppt = new XMLSlideShow(new ByteArrayInputStream(out.toByteArray())); + Dimension pgsize = ppt.getPageSize(); + for (XSLFSlide xmlSlide : ppt.getSlides()) { +// System.out.println("slide-" + (i + 1)); +// System.out.println("" + xmlSlide[i].getTitle()); + + BufferedImage img = new BufferedImage(pgsize.width, pgsize.height, BufferedImage.TYPE_INT_RGB); + Graphics2D graphics = img.createGraphics(); + + // draw stuff + xmlSlide.draw(graphics); + + // Also try to read notes + XSLFNotes notes = xmlSlide.getNotes(); + if(notes != null) { + for (XSLFShape note : notes) { + DrawFactory df = DrawFactory.getInstance(graphics); + Drawable d = df.getDrawable(note); + d.draw(graphics); + + if (note instanceof XSLFTextShape) { + XSLFTextShape txShape = (XSLFTextShape) note; + for (XSLFTextParagraph xslfParagraph : txShape.getTextParagraphs()) { + xslfParagraph.getText(); + } + } + } + } + } + + ppt.close(); + } + // a test-case to test this locally without executing the full TestAllFiles @Test public void test() throws Exception { - InputStream stream = new FileInputStream("test-data/slideshow/testPPT.pptx"); + InputStream stream = new FileInputStream("test-data/slideshow/SampleShow.pptx"); try { handleFile(stream); } finally { stream.close(); } } + + + // a test-case to test this locally without executing the full TestAllFiles + @Test + public void testExtractor() throws Exception { + handleExtracting(new File("test-data/slideshow/testPPT.thmx")); + } } \ No newline at end of file diff --git a/src/integrationtest/org/apache/poi/stress/XSSFFileHandler.java b/src/integrationtest/org/apache/poi/stress/XSSFFileHandler.java index 54a386ea0..a268ed465 100644 --- a/src/integrationtest/org/apache/poi/stress/XSSFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/XSSFFileHandler.java @@ -17,6 +17,7 @@ package org.apache.poi.stress; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileInputStream; import java.io.InputStream; @@ -71,4 +72,10 @@ public class XSSFFileHandler extends SpreadsheetHandler { stream.close(); } } + + // a test-case to test this locally without executing the full TestAllFiles + @Test + public void testExtractor() throws Exception { + handleExtracting(new File("test-data/spreadsheet/56278.xlsx")); + } } \ No newline at end of file diff --git a/src/integrationtest/org/apache/poi/stress/XWPFFileHandler.java b/src/integrationtest/org/apache/poi/stress/XWPFFileHandler.java index a96d46da3..c097dc9f7 100644 --- a/src/integrationtest/org/apache/poi/stress/XWPFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/XWPFFileHandler.java @@ -16,13 +16,15 @@ ==================================================================== */ package org.apache.poi.stress; +import java.io.File; import java.io.FileInputStream; import java.io.InputStream; +import java.io.PushbackInputStream; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.junit.Test; -public class XWPFFileHandler implements FileHandler { +public class XWPFFileHandler extends AbstractFileHandler { @Override public void handleFile(InputStream stream) throws Exception { // ignore password protected files @@ -36,12 +38,16 @@ public class XWPFFileHandler implements FileHandler { // a test-case to test this locally without executing the full TestAllFiles @Test public void test() throws Exception { - InputStream stream = new FileInputStream("test-data/document/footnotes.docx"); + File file = new File("test-data/document/51921-Word-Crash067.docx"); + + InputStream stream = new PushbackInputStream(new FileInputStream(file), 100000); try { handleFile(stream); } finally { stream.close(); } + + handleExtracting(file); } } \ No newline at end of file diff --git a/src/java/org/apache/poi/EmptyFileException.java b/src/java/org/apache/poi/EmptyFileException.java new file mode 100644 index 000000000..ddbd14280 --- /dev/null +++ b/src/java/org/apache/poi/EmptyFileException.java @@ -0,0 +1,28 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi; + +/** + * Exception thrown if an Empty (zero byte) file is supplied + */ +public class EmptyFileException extends IllegalArgumentException { + private static final long serialVersionUID = 1536449292174360166L; + + public EmptyFileException() { + super("The supplied file was empty (zero bytes long)"); + } +} \ No newline at end of file diff --git a/src/java/org/apache/poi/EncryptedDocumentException.java b/src/java/org/apache/poi/EncryptedDocumentException.java index 12196c80c..4ac6123e4 100644 --- a/src/java/org/apache/poi/EncryptedDocumentException.java +++ b/src/java/org/apache/poi/EncryptedDocumentException.java @@ -16,9 +16,10 @@ ==================================================================== */ package org.apache.poi; -@SuppressWarnings("serial") public class EncryptedDocumentException extends IllegalStateException { + private static final long serialVersionUID = 7276950444540469193L; + public EncryptedDocumentException(String s) { super(s); } diff --git a/src/java/org/apache/poi/POIDocument.java b/src/java/org/apache/poi/POIDocument.java index 950e5eb3e..4345d4b1c 100644 --- a/src/java/org/apache/poi/POIDocument.java +++ b/src/java/org/apache/poi/POIDocument.java @@ -30,14 +30,11 @@ import org.apache.poi.hpsf.PropertySet; import org.apache.poi.hpsf.PropertySetFactory; import org.apache.poi.hpsf.SummaryInformation; import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.poifs.filesystem.Entry; -import org.apache.poi.poifs.filesystem.EntryUtils; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.Internal; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -45,8 +42,6 @@ import org.apache.poi.util.POILogger; * This holds the common functionality for all POI * Document classes. * Currently, this relates to Document Information Properties - * - * @author Nick Burch */ public abstract class POIDocument { /** Holds metadata on our document */ @@ -72,20 +67,23 @@ public abstract class POIDocument { } /** - * @deprecated use {@link POIDocument#POIDocument(DirectoryNode)} instead + * Constructs from an old-style OPOIFS */ - @Deprecated - protected POIDocument(DirectoryNode dir, POIFSFileSystem fs) { - this.directory = dir; - } - - protected POIDocument(POIFSFileSystem fs) { + protected POIDocument(OPOIFSFileSystem fs) { this(fs.getRoot()); } - + /** + * Constructs from an old-style OPOIFS + */ protected POIDocument(NPOIFSFileSystem fs) { this(fs.getRoot()); } + /** + * Constructs from the default POIFS + */ + protected POIDocument(POIFSFileSystem fs) { + this(fs.getRoot()); + } /** * Fetch the Document Summary Information of the document @@ -179,12 +177,13 @@ public abstract class POIDocument { protected PropertySet getPropertySet(String setName, EncryptionInfo encryptionInfo) { DirectoryNode dirNode = directory; + NPOIFSFileSystem encPoifs = null; if (encryptionInfo != null) { try { InputStream is = encryptionInfo.getDecryptor().getDataStream(directory); - POIFSFileSystem poifs = new POIFSFileSystem(is); + encPoifs = new NPOIFSFileSystem(is); is.close(); - dirNode = poifs.getRoot(); + dirNode = encPoifs.getRoot(); } catch (Exception e) { logger.log(POILogger.ERROR, "Error getting encrypted property set with name " + setName, e); return null; @@ -208,6 +207,11 @@ public abstract class POIDocument { try { // Create the Property Set PropertySet set = PropertySetFactory.create(dis); + // Tidy up if needed + if (encPoifs != null) { + encPoifs.close(); + } + // Return the properties return set; } catch(IOException ie) { // Must be corrupt or something like that @@ -218,26 +222,39 @@ public abstract class POIDocument { } return null; } + + /** + * Writes out the updated standard Document Information Properties (HPSF) + * into the currently open NPOIFSFileSystem + * TODO Implement in-place update + * + * @throws IOException if an error when writing to the open + * {@link NPOIFSFileSystem} occurs + * TODO throws exception if open from stream not file + */ + protected void writeProperties() throws IOException { + throw new IllegalStateException("In-place write is not yet supported"); + } /** - * Writes out the standard Documment Information Properties (HPSF) + * Writes out the standard Document Information Properties (HPSF) * @param outFS the POIFSFileSystem to write the properties into * * @throws IOException if an error when writing to the - * {@link POIFSFileSystem} occurs + * {@link NPOIFSFileSystem} occurs */ - protected void writeProperties(POIFSFileSystem outFS) throws IOException { + protected void writeProperties(NPOIFSFileSystem outFS) throws IOException { writeProperties(outFS, null); } /** - * Writes out the standard Documment Information Properties (HPSF) - * @param outFS the POIFSFileSystem to write the properties into + * Writes out the standard Document Information Properties (HPSF) + * @param outFS the NPOIFSFileSystem to write the properties into * @param writtenEntries a list of POIFS entries to add the property names too * * @throws IOException if an error when writing to the - * {@link POIFSFileSystem} occurs + * {@link NPOIFSFileSystem} occurs */ - protected void writeProperties(POIFSFileSystem outFS, List writtenEntries) throws IOException { + protected void writeProperties(NPOIFSFileSystem outFS, List writtenEntries) throws IOException { SummaryInformation si = getSummaryInformation(); if (si != null) { writePropertySet(SummaryInformation.DEFAULT_STREAM_NAME, si, outFS); @@ -258,12 +275,12 @@ public abstract class POIDocument { * Writes out a given ProperySet * @param name the (POIFS Level) name of the property to write * @param set the PropertySet to write out - * @param outFS the POIFSFileSystem to write the property into + * @param outFS the NPOIFSFileSystem to write the property into * * @throws IOException if an error when writing to the - * {@link POIFSFileSystem} occurs + * {@link NPOIFSFileSystem} occurs */ - protected void writePropertySet(String name, PropertySet set, POIFSFileSystem outFS) throws IOException { + protected void writePropertySet(String name, PropertySet set, NPOIFSFileSystem outFS) throws IOException { try { MutablePropertySet mSet = new MutablePropertySet(set); ByteArrayOutputStream bOut = new ByteArrayOutputStream(); @@ -288,55 +305,4 @@ public abstract class POIDocument { * @throws IOException thrown on errors writing to the stream */ public abstract void write(OutputStream out) throws IOException; - - /** - * Copies nodes from one POIFS to the other minus the excepts - * @param source is the source POIFS to copy from - * @param target is the target POIFS to copy to - * @param excepts is a list of Strings specifying what nodes NOT to copy - * - * @throws IOException thrown on errors writing to the target file system. - * - * @deprecated Use {@link EntryUtils#copyNodes(DirectoryEntry, DirectoryEntry, List)} instead - */ - @Deprecated - protected void copyNodes( POIFSFileSystem source, POIFSFileSystem target, - List excepts ) throws IOException { - EntryUtils.copyNodes( source, target, excepts ); - } - - /** - * Copies nodes from one POIFS to the other minus the excepts - * @param sourceRoot is the source POIFS to copy from - * @param targetRoot is the target POIFS to copy to - * @param excepts is a list of Strings specifying what nodes NOT to copy - * - * @throws IOException thrown on errors writing to the target directory node. - * - * @deprecated Use {@link EntryUtils#copyNodes(DirectoryEntry, DirectoryEntry, List)} instead - */ - @Deprecated - protected void copyNodes( DirectoryNode sourceRoot, - DirectoryNode targetRoot, List excepts ) throws IOException - { - EntryUtils.copyNodes( sourceRoot, targetRoot, excepts ); - } - - /** - * Copies an Entry into a target POIFS directory, recursively - * - * @param entry the entry to copy from - * @param target the entry to write to - * - * @throws IOException thrown on errors writing to the target directory entry. - * - * @deprecated Use {@link EntryUtils#copyNodeRecursively(Entry, DirectoryEntry)} instead - */ - @Internal - @Deprecated - protected void copyNodeRecursively( Entry entry, DirectoryEntry target ) - throws IOException - { - EntryUtils.copyNodeRecursively( entry, target ); - } } diff --git a/src/java/org/apache/poi/POIOLE2TextExtractor.java b/src/java/org/apache/poi/POIOLE2TextExtractor.java index c0f4cbd1d..5dd1d755e 100644 --- a/src/java/org/apache/poi/POIOLE2TextExtractor.java +++ b/src/java/org/apache/poi/POIOLE2TextExtractor.java @@ -20,7 +20,6 @@ import org.apache.poi.hpsf.DocumentSummaryInformation; import org.apache.poi.hpsf.SummaryInformation; import org.apache.poi.hpsf.extractor.HPSFPropertiesExtractor; import org.apache.poi.poifs.filesystem.DirectoryEntry; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; /** * Common Parent for OLE2 based Text Extractors @@ -34,15 +33,27 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; * @see org.apache.poi.hwpf.extractor.WordExtractor */ public abstract class POIOLE2TextExtractor extends POITextExtractor { + /** The POIDocument that's open */ + protected POIDocument document; + /** * Creates a new text extractor for the given document * * @param document The POIDocument to use in this extractor. */ public POIOLE2TextExtractor(POIDocument document) { - super(document); + this.document = document; } + /** + * Creates a new text extractor, using the same + * document as another text extractor. Normally + * only used by properties extractors. + */ + protected POIOLE2TextExtractor(POIOLE2TextExtractor otherExtractor) { + this.document = otherExtractor.document; + } + /** * Returns the document information metadata for the document * @@ -81,17 +92,4 @@ public abstract class POIOLE2TextExtractor extends POITextExtractor { { return document.directory; } - - /** - * Return the underlying POIFS FileSystem of this document. - * - * @return the POIFSFileSystem that is associated with the POIDocument of this extractor. - * - * @deprecated Use {@link #getRoot()} instead - */ - @Deprecated - public POIFSFileSystem getFileSystem() - { - return document.directory.getFileSystem(); - } } diff --git a/src/java/org/apache/poi/POITextExtractor.java b/src/java/org/apache/poi/POITextExtractor.java index e18078b46..6514ad5d1 100644 --- a/src/java/org/apache/poi/POITextExtractor.java +++ b/src/java/org/apache/poi/POITextExtractor.java @@ -31,24 +31,6 @@ import java.io.IOException; * @see org.apache.poi.hwpf.extractor.WordExtractor */ public abstract class POITextExtractor implements Closeable { - /** The POIDocument that's open */ - protected POIDocument document; - - /** - * Creates a new text extractor for the given document - */ - public POITextExtractor(POIDocument document) { - this.document = document; - } - /** - * Creates a new text extractor, using the same - * document as another text extractor. Normally - * only used by properties extractors. - */ - protected POITextExtractor(POITextExtractor otherExtractor) { - this.document = otherExtractor.document; - } - /** * Retrieves all the text from the document. * How cells, paragraphs etc are separated in the text diff --git a/src/java/org/apache/poi/ddf/EscherPropertyFactory.java b/src/java/org/apache/poi/ddf/EscherPropertyFactory.java index 3dcce79b8..efea00438 100644 --- a/src/java/org/apache/poi/ddf/EscherPropertyFactory.java +++ b/src/java/org/apache/poi/ddf/EscherPropertyFactory.java @@ -82,6 +82,13 @@ public final class EscherPropertyFactory { pos += ((EscherArrayProperty)p).setArrayData(data, pos); } else { byte[] complexData = ((EscherComplexProperty)p).getComplexData(); + + int leftover = data.length-pos; + if(leftover < complexData.length){ + throw new IllegalStateException("Could not read complex escher property, lenght was " + complexData.length + ", but had only " + + leftover + " bytes left"); + } + System.arraycopy(data, pos, complexData, 0, complexData.length); pos += complexData.length; } diff --git a/src/java/org/apache/poi/hpsf/HPSFPropertiesOnlyDocument.java b/src/java/org/apache/poi/hpsf/HPSFPropertiesOnlyDocument.java index f1b9ca962..9b0f84d47 100644 --- a/src/java/org/apache/poi/hpsf/HPSFPropertiesOnlyDocument.java +++ b/src/java/org/apache/poi/hpsf/HPSFPropertiesOnlyDocument.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.poi.POIDocument; import org.apache.poi.poifs.filesystem.EntryUtils; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; /** @@ -36,6 +37,9 @@ public class HPSFPropertiesOnlyDocument extends POIDocument { public HPSFPropertiesOnlyDocument(NPOIFSFileSystem fs) { super(fs.getRoot()); } + public HPSFPropertiesOnlyDocument(OPOIFSFileSystem fs) { + super(fs); + } public HPSFPropertiesOnlyDocument(POIFSFileSystem fs) { super(fs); } @@ -44,7 +48,7 @@ public class HPSFPropertiesOnlyDocument extends POIDocument { * Write out, with any properties changes, but nothing else */ public void write(OutputStream out) throws IOException { - POIFSFileSystem fs = new POIFSFileSystem(); + NPOIFSFileSystem fs = new NPOIFSFileSystem(); // For tracking what we've written out, so far List excepts = new ArrayList(1); diff --git a/src/java/org/apache/poi/hpsf/Section.java b/src/java/org/apache/poi/hpsf/Section.java index 0c97a0e68..3c8e5b7ce 100644 --- a/src/java/org/apache/poi/hpsf/Section.java +++ b/src/java/org/apache/poi/hpsf/Section.java @@ -285,7 +285,7 @@ public class Section /* * Extract the dictionary (if available). */ - dictionary = (Map) getProperty(0); + dictionary = (Map) getProperty(0); } diff --git a/src/java/org/apache/poi/hpsf/extractor/HPSFPropertiesExtractor.java b/src/java/org/apache/poi/hpsf/extractor/HPSFPropertiesExtractor.java index ce5301ac6..b7967f333 100644 --- a/src/java/org/apache/poi/hpsf/extractor/HPSFPropertiesExtractor.java +++ b/src/java/org/apache/poi/hpsf/extractor/HPSFPropertiesExtractor.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.util.Iterator; import org.apache.poi.POIDocument; +import org.apache.poi.POIOLE2TextExtractor; import org.apache.poi.POITextExtractor; import org.apache.poi.hpsf.CustomProperties; import org.apache.poi.hpsf.DocumentSummaryInformation; @@ -39,10 +40,10 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; * build in and custom, returning them in * textual form. */ -public class HPSFPropertiesExtractor extends POITextExtractor { +public class HPSFPropertiesExtractor extends POIOLE2TextExtractor { private Closeable toClose; - public HPSFPropertiesExtractor(POITextExtractor mainExtractor) { + public HPSFPropertiesExtractor(POIOLE2TextExtractor mainExtractor) { super(mainExtractor); } public HPSFPropertiesExtractor(POIDocument doc) { @@ -57,6 +58,10 @@ public class HPSFPropertiesExtractor extends POITextExtractor { } public String getDocumentSummaryInformationText() { + if(document == null) { // event based extractor does not have a document + return ""; + } + DocumentSummaryInformation dsi = document.getDocumentSummaryInformation(); StringBuffer text = new StringBuffer(); @@ -78,6 +83,10 @@ public class HPSFPropertiesExtractor extends POITextExtractor { return text.toString(); } public String getSummaryInformationText() { + if(document == null) { // event based extractor does not have a document + return ""; + } + SummaryInformation si = document.getSummaryInformation(); // Just normal properties diff --git a/src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java b/src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java index c9f987271..ca35c631b 100644 --- a/src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java +++ b/src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java @@ -34,7 +34,7 @@ import org.apache.poi.hssf.record.DrawingGroupRecord; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.hssf.usermodel.HSSFPatriarch; import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; /** * Utility for representing drawings contained in a binary Excel file as a XML tree @@ -138,7 +138,7 @@ public class BiffDrawingToXml { } public static void writeToFile(OutputStream fos, InputStream xlsWorkbook, boolean excludeWorkbookRecords, String[] params) throws IOException { - POIFSFileSystem fs = new POIFSFileSystem(xlsWorkbook); + NPOIFSFileSystem fs = new NPOIFSFileSystem(xlsWorkbook); HSSFWorkbook workbook = new HSSFWorkbook(fs); InternalWorkbook internalWorkbook = getInternalWorkbook(workbook); DrawingGroupRecord r = (DrawingGroupRecord) internalWorkbook.findFirstRecordBySid(DrawingGroupRecord.sid); diff --git a/src/java/org/apache/poi/hssf/dev/BiffViewer.java b/src/java/org/apache/poi/hssf/dev/BiffViewer.java index 5451b2789..3afd25a4a 100644 --- a/src/java/org/apache/poi/hssf/dev/BiffViewer.java +++ b/src/java/org/apache/poi/hssf/dev/BiffViewer.java @@ -17,13 +17,63 @@ package org.apache.poi.hssf.dev; -import java.io.*; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.Writer; import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.record.*; import org.apache.poi.hssf.record.RecordInputStream.LeftoverDataException; -import org.apache.poi.hssf.record.chart.*; +import org.apache.poi.hssf.record.chart.AreaFormatRecord; +import org.apache.poi.hssf.record.chart.AreaRecord; +import org.apache.poi.hssf.record.chart.AxisLineFormatRecord; +import org.apache.poi.hssf.record.chart.AxisOptionsRecord; +import org.apache.poi.hssf.record.chart.AxisParentRecord; +import org.apache.poi.hssf.record.chart.AxisRecord; +import org.apache.poi.hssf.record.chart.AxisUsedRecord; +import org.apache.poi.hssf.record.chart.BarRecord; +import org.apache.poi.hssf.record.chart.BeginRecord; +import org.apache.poi.hssf.record.chart.CatLabRecord; +import org.apache.poi.hssf.record.chart.CategorySeriesAxisRecord; +import org.apache.poi.hssf.record.chart.ChartEndBlockRecord; +import org.apache.poi.hssf.record.chart.ChartEndObjectRecord; +import org.apache.poi.hssf.record.chart.ChartFRTInfoRecord; +import org.apache.poi.hssf.record.chart.ChartFormatRecord; +import org.apache.poi.hssf.record.chart.ChartRecord; +import org.apache.poi.hssf.record.chart.ChartStartBlockRecord; +import org.apache.poi.hssf.record.chart.ChartStartObjectRecord; +import org.apache.poi.hssf.record.chart.DatRecord; +import org.apache.poi.hssf.record.chart.DataFormatRecord; +import org.apache.poi.hssf.record.chart.DefaultDataLabelTextPropertiesRecord; +import org.apache.poi.hssf.record.chart.EndRecord; +import org.apache.poi.hssf.record.chart.FontBasisRecord; +import org.apache.poi.hssf.record.chart.FontIndexRecord; +import org.apache.poi.hssf.record.chart.FrameRecord; +import org.apache.poi.hssf.record.chart.LegendRecord; +import org.apache.poi.hssf.record.chart.LineFormatRecord; +import org.apache.poi.hssf.record.chart.LinkedDataRecord; +import org.apache.poi.hssf.record.chart.ObjectLinkRecord; +import org.apache.poi.hssf.record.chart.PlotAreaRecord; +import org.apache.poi.hssf.record.chart.PlotGrowthRecord; +import org.apache.poi.hssf.record.chart.SeriesIndexRecord; +import org.apache.poi.hssf.record.chart.SeriesListRecord; +import org.apache.poi.hssf.record.chart.SeriesRecord; +import org.apache.poi.hssf.record.chart.SeriesTextRecord; +import org.apache.poi.hssf.record.chart.SeriesToChartGroupRecord; +import org.apache.poi.hssf.record.chart.SheetPropertiesRecord; +import org.apache.poi.hssf.record.chart.TextRecord; +import org.apache.poi.hssf.record.chart.TickRecord; +import org.apache.poi.hssf.record.chart.UnitsRecord; +import org.apache.poi.hssf.record.chart.ValueRangeRecord; import org.apache.poi.hssf.record.pivottable.DataItemRecord; import org.apache.poi.hssf.record.pivottable.ExtendedPivotTableViewFieldsRecord; import org.apache.poi.hssf.record.pivottable.PageItemRecord; @@ -32,330 +82,330 @@ import org.apache.poi.hssf.record.pivottable.ViewDefinitionRecord; import org.apache.poi.hssf.record.pivottable.ViewFieldsRecord; import org.apache.poi.hssf.record.pivottable.ViewSourceRecord; import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.util.HexDump; import org.apache.poi.util.LittleEndian; /** * Utillity for reading in BIFF8 records and displaying data from them. - * - *@author Andrew C. Oliver (acoliver at apache dot org) - *@author Glen Stampoultzis (glens at apache.org) - *@see #main + * @see #main */ public final class BiffViewer { - static final char[] NEW_LINE_CHARS = System.getProperty("line.separator").toCharArray(); + static final char[] NEW_LINE_CHARS = System.getProperty("line.separator").toCharArray(); private BiffViewer() { - // no instances of this class - } + // no instances of this class + } - /** - * Create an array of records from an input stream - * - *@param is the InputStream from which the records will be obtained - *@return an array of Records created from the InputStream - *@exception RecordFormatException on error processing the InputStream - */ - public static Record[] createRecords(InputStream is, PrintStream ps, BiffRecordListener recListener, boolean dumpInterpretedRecords) - throws RecordFormatException { - List temp = new ArrayList(); + /** + * Create an array of records from an input stream + * + *@param is the InputStream from which the records will be obtained + *@return an array of Records created from the InputStream + *@exception RecordFormatException on error processing the InputStream + */ + public static Record[] createRecords(InputStream is, PrintStream ps, BiffRecordListener recListener, boolean dumpInterpretedRecords) + throws RecordFormatException { + List temp = new ArrayList(); - RecordInputStream recStream = new RecordInputStream(is); - while (true) { - boolean hasNext; - try { - hasNext = recStream.hasNextRecord(); - } catch (LeftoverDataException e) { - e.printStackTrace(); - System.err.println("Discarding " + recStream.remaining() + " bytes and continuing"); - recStream.readRemainder(); - hasNext = recStream.hasNextRecord(); - } - if (!hasNext) { - break; - } - recStream.nextRecord(); - if (recStream.getSid() == 0) { - continue; - } - Record record; - if (dumpInterpretedRecords) { - record = createRecord (recStream); - if (record.getSid() == ContinueRecord.sid) { - continue; - } - temp.add(record); + RecordInputStream recStream = new RecordInputStream(is); + while (true) { + boolean hasNext; + try { + hasNext = recStream.hasNextRecord(); + } catch (LeftoverDataException e) { + e.printStackTrace(); + System.err.println("Discarding " + recStream.remaining() + " bytes and continuing"); + recStream.readRemainder(); + hasNext = recStream.hasNextRecord(); + } + if (!hasNext) { + break; + } + recStream.nextRecord(); + if (recStream.getSid() == 0) { + continue; + } + Record record; + if (dumpInterpretedRecords) { + record = createRecord (recStream); + if (record.getSid() == ContinueRecord.sid) { + continue; + } + temp.add(record); - if (dumpInterpretedRecords) { - for (String header : recListener.getRecentHeaders()) { - ps.println(header); - } - ps.print(record.toString()); - } - } else { - recStream.readRemainder(); - } - ps.println(); - } - Record[] result = new Record[temp.size()]; - temp.toArray(result); - return result; - } + if (dumpInterpretedRecords) { + for (String header : recListener.getRecentHeaders()) { + ps.println(header); + } + ps.print(record.toString()); + } + } else { + recStream.readRemainder(); + } + ps.println(); + } + Record[] result = new Record[temp.size()]; + temp.toArray(result); + return result; + } - /** - * Essentially a duplicate of RecordFactory. Kept separate as not to screw - * up non-debug operations. - * - */ - private static Record createRecord(RecordInputStream in) { - switch (in.getSid()) { - case AreaFormatRecord.sid: return new AreaFormatRecord(in); - case AreaRecord.sid: return new AreaRecord(in); - case ArrayRecord.sid: return new ArrayRecord(in); - case AxisLineFormatRecord.sid: return new AxisLineFormatRecord(in); - case AxisOptionsRecord.sid: return new AxisOptionsRecord(in); - case AxisParentRecord.sid: return new AxisParentRecord(in); - case AxisRecord.sid: return new AxisRecord(in); - case AxisUsedRecord.sid: return new AxisUsedRecord(in); - case AutoFilterInfoRecord.sid: return new AutoFilterInfoRecord(in); - case BOFRecord.sid: return new BOFRecord(in); - case BackupRecord.sid: return new BackupRecord(in); - case BarRecord.sid: return new BarRecord(in); - case BeginRecord.sid: return new BeginRecord(in); - case BlankRecord.sid: return new BlankRecord(in); - case BookBoolRecord.sid: return new BookBoolRecord(in); - case BoolErrRecord.sid: return new BoolErrRecord(in); - case BottomMarginRecord.sid: return new BottomMarginRecord(in); - case BoundSheetRecord.sid: return new BoundSheetRecord(in); - case CFHeaderRecord.sid: return new CFHeaderRecord(in); - case CFRuleRecord.sid: return new CFRuleRecord(in); - case CalcCountRecord.sid: return new CalcCountRecord(in); - case CalcModeRecord.sid: return new CalcModeRecord(in); - case CategorySeriesAxisRecord.sid: return new CategorySeriesAxisRecord(in); - case ChartFormatRecord.sid: return new ChartFormatRecord(in); - case ChartRecord.sid: return new ChartRecord(in); - case CodepageRecord.sid: return new CodepageRecord(in); - case ColumnInfoRecord.sid: return new ColumnInfoRecord(in); - case ContinueRecord.sid: return new ContinueRecord(in); - case CountryRecord.sid: return new CountryRecord(in); - case DBCellRecord.sid: return new DBCellRecord(in); - case DSFRecord.sid: return new DSFRecord(in); - case DatRecord.sid: return new DatRecord(in); - case DataFormatRecord.sid: return new DataFormatRecord(in); - case DateWindow1904Record.sid: return new DateWindow1904Record(in); - case DConRefRecord.sid: return new DConRefRecord(in); - case DefaultColWidthRecord.sid:return new DefaultColWidthRecord(in); - case DefaultDataLabelTextPropertiesRecord.sid: return new DefaultDataLabelTextPropertiesRecord(in); - case DefaultRowHeightRecord.sid: return new DefaultRowHeightRecord(in); - case DeltaRecord.sid: return new DeltaRecord(in); - case DimensionsRecord.sid: return new DimensionsRecord(in); - case DrawingGroupRecord.sid: return new DrawingGroupRecord(in); - case DrawingRecordForBiffViewer.sid: return new DrawingRecordForBiffViewer(in); - case DrawingSelectionRecord.sid: return new DrawingSelectionRecord(in); - case DVRecord.sid: return new DVRecord(in); - case DVALRecord.sid: return new DVALRecord(in); - case EOFRecord.sid: return new EOFRecord(in); - case EndRecord.sid: return new EndRecord(in); - case ExtSSTRecord.sid: return new ExtSSTRecord(in); - case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in); - case ExternSheetRecord.sid: return new ExternSheetRecord(in); - case ExternalNameRecord.sid: return new ExternalNameRecord(in); - case FeatRecord.sid: return new FeatRecord(in); - case FeatHdrRecord.sid: return new FeatHdrRecord(in); - case FilePassRecord.sid: return new FilePassRecord(in); - case FileSharingRecord.sid: return new FileSharingRecord(in); - case FnGroupCountRecord.sid: return new FnGroupCountRecord(in); - case FontBasisRecord.sid: return new FontBasisRecord(in); - case FontIndexRecord.sid: return new FontIndexRecord(in); - case FontRecord.sid: return new FontRecord(in); - case FooterRecord.sid: return new FooterRecord(in); - case FormatRecord.sid: return new FormatRecord(in); - case FormulaRecord.sid: return new FormulaRecord(in); - case FrameRecord.sid: return new FrameRecord(in); - case GridsetRecord.sid: return new GridsetRecord(in); - case GutsRecord.sid: return new GutsRecord(in); - case HCenterRecord.sid: return new HCenterRecord(in); - case HeaderRecord.sid: return new HeaderRecord(in); - case HideObjRecord.sid: return new HideObjRecord(in); - case HorizontalPageBreakRecord.sid: return new HorizontalPageBreakRecord(in); - case HyperlinkRecord.sid: return new HyperlinkRecord(in); - case IndexRecord.sid: return new IndexRecord(in); - case InterfaceEndRecord.sid: return InterfaceEndRecord.create(in); - case InterfaceHdrRecord.sid: return new InterfaceHdrRecord(in); - case IterationRecord.sid: return new IterationRecord(in); - case LabelRecord.sid: return new LabelRecord(in); - case LabelSSTRecord.sid: return new LabelSSTRecord(in); - case LeftMarginRecord.sid: return new LeftMarginRecord(in); - case LegendRecord.sid: return new LegendRecord(in); - case LineFormatRecord.sid: return new LineFormatRecord(in); - case LinkedDataRecord.sid: return new LinkedDataRecord(in); - case MMSRecord.sid: return new MMSRecord(in); - case MergeCellsRecord.sid: return new MergeCellsRecord(in); - case MulBlankRecord.sid: return new MulBlankRecord(in); - case MulRKRecord.sid: return new MulRKRecord(in); - case NameRecord.sid: return new NameRecord(in); - case NameCommentRecord.sid: return new NameCommentRecord(in); - case NoteRecord.sid: return new NoteRecord(in); - case NumberRecord.sid: return new NumberRecord(in); - case ObjRecord.sid: return new ObjRecord(in); - case ObjectLinkRecord.sid: return new ObjectLinkRecord(in); - case PaletteRecord.sid: return new PaletteRecord(in); - case PaneRecord.sid: return new PaneRecord(in); - case PasswordRecord.sid: return new PasswordRecord(in); - case PasswordRev4Record.sid: return new PasswordRev4Record(in); - case PlotAreaRecord.sid: return new PlotAreaRecord(in); - case PlotGrowthRecord.sid: return new PlotGrowthRecord(in); - case PrecisionRecord.sid: return new PrecisionRecord(in); - case PrintGridlinesRecord.sid: return new PrintGridlinesRecord(in); - case PrintHeadersRecord.sid: return new PrintHeadersRecord(in); - case PrintSetupRecord.sid: return new PrintSetupRecord(in); - case ProtectRecord.sid: return new ProtectRecord(in); - case ProtectionRev4Record.sid: return new ProtectionRev4Record(in); - case RKRecord.sid: return new RKRecord(in); - case RecalcIdRecord.sid: return new RecalcIdRecord(in); - case RefModeRecord.sid: return new RefModeRecord(in); - case RefreshAllRecord.sid: return new RefreshAllRecord(in); - case RightMarginRecord.sid: return new RightMarginRecord(in); - case RowRecord.sid: return new RowRecord(in); - case SCLRecord.sid: return new SCLRecord(in); - case SSTRecord.sid: return new SSTRecord(in); - case SaveRecalcRecord.sid: return new SaveRecalcRecord(in); - case SelectionRecord.sid: return new SelectionRecord(in); - case SeriesIndexRecord.sid: return new SeriesIndexRecord(in); - case SeriesListRecord.sid: return new SeriesListRecord(in); - case SeriesRecord.sid: return new SeriesRecord(in); - case SeriesTextRecord.sid: return new SeriesTextRecord(in); - case SeriesToChartGroupRecord.sid: return new SeriesToChartGroupRecord(in); - case SharedFormulaRecord.sid: return new SharedFormulaRecord(in); - case SheetPropertiesRecord.sid:return new SheetPropertiesRecord(in); - case StringRecord.sid: return new StringRecord(in); - case StyleRecord.sid: return new StyleRecord(in); - case SupBookRecord.sid: return new SupBookRecord(in); - case TabIdRecord.sid: return new TabIdRecord(in); - case TableStylesRecord.sid: return new TableStylesRecord(in); - case TableRecord.sid: return new TableRecord(in); - case TextObjectRecord.sid: return new TextObjectRecord(in); - case TextRecord.sid: return new TextRecord(in); - case TickRecord.sid: return new TickRecord(in); - case TopMarginRecord.sid: return new TopMarginRecord(in); - case UncalcedRecord.sid: return new UncalcedRecord(in); - case UnitsRecord.sid: return new UnitsRecord(in); - case UseSelFSRecord.sid: return new UseSelFSRecord(in); - case VCenterRecord.sid: return new VCenterRecord(in); - case ValueRangeRecord.sid: return new ValueRangeRecord(in); - case VerticalPageBreakRecord.sid: return new VerticalPageBreakRecord(in); - case WSBoolRecord.sid: return new WSBoolRecord(in); - case WindowOneRecord.sid: return new WindowOneRecord(in); - case WindowProtectRecord.sid: return new WindowProtectRecord(in); - case WindowTwoRecord.sid: return new WindowTwoRecord(in); - case WriteAccessRecord.sid: return new WriteAccessRecord(in); - case WriteProtectRecord.sid: return new WriteProtectRecord(in); + /** + * Essentially a duplicate of RecordFactory. Kept separate as not to screw + * up non-debug operations. + * + */ + private static Record createRecord(RecordInputStream in) { + switch (in.getSid()) { + case AreaFormatRecord.sid: return new AreaFormatRecord(in); + case AreaRecord.sid: return new AreaRecord(in); + case ArrayRecord.sid: return new ArrayRecord(in); + case AxisLineFormatRecord.sid: return new AxisLineFormatRecord(in); + case AxisOptionsRecord.sid: return new AxisOptionsRecord(in); + case AxisParentRecord.sid: return new AxisParentRecord(in); + case AxisRecord.sid: return new AxisRecord(in); + case AxisUsedRecord.sid: return new AxisUsedRecord(in); + case AutoFilterInfoRecord.sid: return new AutoFilterInfoRecord(in); + case BOFRecord.sid: return new BOFRecord(in); + case BackupRecord.sid: return new BackupRecord(in); + case BarRecord.sid: return new BarRecord(in); + case BeginRecord.sid: return new BeginRecord(in); + case BlankRecord.sid: return new BlankRecord(in); + case BookBoolRecord.sid: return new BookBoolRecord(in); + case BoolErrRecord.sid: return new BoolErrRecord(in); + case BottomMarginRecord.sid: return new BottomMarginRecord(in); + case BoundSheetRecord.sid: return new BoundSheetRecord(in); + case CFHeaderRecord.sid: return new CFHeaderRecord(in); + case CFHeader12Record.sid: return new CFHeader12Record(in); + case CFRuleRecord.sid: return new CFRuleRecord(in); + case CFRule12Record.sid: return new CFRule12Record(in); + // TODO Add CF Ex, and remove from UnknownRecord + case CalcCountRecord.sid: return new CalcCountRecord(in); + case CalcModeRecord.sid: return new CalcModeRecord(in); + case CategorySeriesAxisRecord.sid:return new CategorySeriesAxisRecord(in); + case ChartFormatRecord.sid: return new ChartFormatRecord(in); + case ChartRecord.sid: return new ChartRecord(in); + case CodepageRecord.sid: return new CodepageRecord(in); + case ColumnInfoRecord.sid: return new ColumnInfoRecord(in); + case ContinueRecord.sid: return new ContinueRecord(in); + case CountryRecord.sid: return new CountryRecord(in); + case DBCellRecord.sid: return new DBCellRecord(in); + case DSFRecord.sid: return new DSFRecord(in); + case DatRecord.sid: return new DatRecord(in); + case DataFormatRecord.sid: return new DataFormatRecord(in); + case DateWindow1904Record.sid: return new DateWindow1904Record(in); + case DConRefRecord.sid: return new DConRefRecord(in); + case DefaultColWidthRecord.sid: return new DefaultColWidthRecord(in); + case DefaultDataLabelTextPropertiesRecord.sid: return new DefaultDataLabelTextPropertiesRecord(in); + case DefaultRowHeightRecord.sid: return new DefaultRowHeightRecord(in); + case DeltaRecord.sid: return new DeltaRecord(in); + case DimensionsRecord.sid: return new DimensionsRecord(in); + case DrawingGroupRecord.sid: return new DrawingGroupRecord(in); + case DrawingRecordForBiffViewer.sid: return new DrawingRecordForBiffViewer(in); + case DrawingSelectionRecord.sid: return new DrawingSelectionRecord(in); + case DVRecord.sid: return new DVRecord(in); + case DVALRecord.sid: return new DVALRecord(in); + case EOFRecord.sid: return new EOFRecord(in); + case EndRecord.sid: return new EndRecord(in); + case ExtSSTRecord.sid: return new ExtSSTRecord(in); + case ExtendedFormatRecord.sid: return new ExtendedFormatRecord(in); + case ExternSheetRecord.sid: return new ExternSheetRecord(in); + case ExternalNameRecord.sid: return new ExternalNameRecord(in); + case FeatRecord.sid: return new FeatRecord(in); + case FeatHdrRecord.sid: return new FeatHdrRecord(in); + case FilePassRecord.sid: return new FilePassRecord(in); + case FileSharingRecord.sid: return new FileSharingRecord(in); + case FnGroupCountRecord.sid: return new FnGroupCountRecord(in); + case FontBasisRecord.sid: return new FontBasisRecord(in); + case FontIndexRecord.sid: return new FontIndexRecord(in); + case FontRecord.sid: return new FontRecord(in); + case FooterRecord.sid: return new FooterRecord(in); + case FormatRecord.sid: return new FormatRecord(in); + case FormulaRecord.sid: return new FormulaRecord(in); + case FrameRecord.sid: return new FrameRecord(in); + case GridsetRecord.sid: return new GridsetRecord(in); + case GutsRecord.sid: return new GutsRecord(in); + case HCenterRecord.sid: return new HCenterRecord(in); + case HeaderRecord.sid: return new HeaderRecord(in); + case HideObjRecord.sid: return new HideObjRecord(in); + case HorizontalPageBreakRecord.sid: return new HorizontalPageBreakRecord(in); + case HyperlinkRecord.sid: return new HyperlinkRecord(in); + case IndexRecord.sid: return new IndexRecord(in); + case InterfaceEndRecord.sid: return InterfaceEndRecord.create(in); + case InterfaceHdrRecord.sid: return new InterfaceHdrRecord(in); + case IterationRecord.sid: return new IterationRecord(in); + case LabelRecord.sid: return new LabelRecord(in); + case LabelSSTRecord.sid: return new LabelSSTRecord(in); + case LeftMarginRecord.sid: return new LeftMarginRecord(in); + case LegendRecord.sid: return new LegendRecord(in); + case LineFormatRecord.sid: return new LineFormatRecord(in); + case LinkedDataRecord.sid: return new LinkedDataRecord(in); + case MMSRecord.sid: return new MMSRecord(in); + case MergeCellsRecord.sid: return new MergeCellsRecord(in); + case MulBlankRecord.sid: return new MulBlankRecord(in); + case MulRKRecord.sid: return new MulRKRecord(in); + case NameRecord.sid: return new NameRecord(in); + case NameCommentRecord.sid: return new NameCommentRecord(in); + case NoteRecord.sid: return new NoteRecord(in); + case NumberRecord.sid: return new NumberRecord(in); + case ObjRecord.sid: return new ObjRecord(in); + case ObjectLinkRecord.sid: return new ObjectLinkRecord(in); + case PaletteRecord.sid: return new PaletteRecord(in); + case PaneRecord.sid: return new PaneRecord(in); + case PasswordRecord.sid: return new PasswordRecord(in); + case PasswordRev4Record.sid: return new PasswordRev4Record(in); + case PlotAreaRecord.sid: return new PlotAreaRecord(in); + case PlotGrowthRecord.sid: return new PlotGrowthRecord(in); + case PrecisionRecord.sid: return new PrecisionRecord(in); + case PrintGridlinesRecord.sid: return new PrintGridlinesRecord(in); + case PrintHeadersRecord.sid: return new PrintHeadersRecord(in); + case PrintSetupRecord.sid: return new PrintSetupRecord(in); + case ProtectRecord.sid: return new ProtectRecord(in); + case ProtectionRev4Record.sid: return new ProtectionRev4Record(in); + case RKRecord.sid: return new RKRecord(in); + case RecalcIdRecord.sid: return new RecalcIdRecord(in); + case RefModeRecord.sid: return new RefModeRecord(in); + case RefreshAllRecord.sid: return new RefreshAllRecord(in); + case RightMarginRecord.sid: return new RightMarginRecord(in); + case RowRecord.sid: return new RowRecord(in); + case SCLRecord.sid: return new SCLRecord(in); + case SSTRecord.sid: return new SSTRecord(in); + case SaveRecalcRecord.sid: return new SaveRecalcRecord(in); + case SelectionRecord.sid: return new SelectionRecord(in); + case SeriesIndexRecord.sid: return new SeriesIndexRecord(in); + case SeriesListRecord.sid: return new SeriesListRecord(in); + case SeriesRecord.sid: return new SeriesRecord(in); + case SeriesTextRecord.sid: return new SeriesTextRecord(in); + case SeriesToChartGroupRecord.sid:return new SeriesToChartGroupRecord(in); + case SharedFormulaRecord.sid: return new SharedFormulaRecord(in); + case SheetPropertiesRecord.sid: return new SheetPropertiesRecord(in); + case StringRecord.sid: return new StringRecord(in); + case StyleRecord.sid: return new StyleRecord(in); + case SupBookRecord.sid: return new SupBookRecord(in); + case TabIdRecord.sid: return new TabIdRecord(in); + case TableStylesRecord.sid: return new TableStylesRecord(in); + case TableRecord.sid: return new TableRecord(in); + case TextObjectRecord.sid: return new TextObjectRecord(in); + case TextRecord.sid: return new TextRecord(in); + case TickRecord.sid: return new TickRecord(in); + case TopMarginRecord.sid: return new TopMarginRecord(in); + case UncalcedRecord.sid: return new UncalcedRecord(in); + case UnitsRecord.sid: return new UnitsRecord(in); + case UseSelFSRecord.sid: return new UseSelFSRecord(in); + case VCenterRecord.sid: return new VCenterRecord(in); + case ValueRangeRecord.sid: return new ValueRangeRecord(in); + case VerticalPageBreakRecord.sid: return new VerticalPageBreakRecord(in); + case WSBoolRecord.sid: return new WSBoolRecord(in); + case WindowOneRecord.sid: return new WindowOneRecord(in); + case WindowProtectRecord.sid: return new WindowProtectRecord(in); + case WindowTwoRecord.sid: return new WindowTwoRecord(in); + case WriteAccessRecord.sid: return new WriteAccessRecord(in); + case WriteProtectRecord.sid: return new WriteProtectRecord(in); - // chart - case CatLabRecord.sid: return new CatLabRecord(in); - case ChartEndBlockRecord.sid: return new ChartEndBlockRecord(in); - case ChartEndObjectRecord.sid: return new ChartEndObjectRecord(in); - case ChartFRTInfoRecord.sid: return new ChartFRTInfoRecord(in); - case ChartStartBlockRecord.sid: return new ChartStartBlockRecord(in); - case ChartStartObjectRecord.sid: return new ChartStartObjectRecord(in); + // chart + case CatLabRecord.sid: return new CatLabRecord(in); + case ChartEndBlockRecord.sid: return new ChartEndBlockRecord(in); + case ChartEndObjectRecord.sid: return new ChartEndObjectRecord(in); + case ChartFRTInfoRecord.sid: return new ChartFRTInfoRecord(in); + case ChartStartBlockRecord.sid: return new ChartStartBlockRecord(in); + case ChartStartObjectRecord.sid: return new ChartStartObjectRecord(in); - // pivot table - case StreamIDRecord.sid: return new StreamIDRecord(in); - case ViewSourceRecord.sid: return new ViewSourceRecord(in); - case PageItemRecord.sid: return new PageItemRecord(in); - case ViewDefinitionRecord.sid: return new ViewDefinitionRecord(in); - case ViewFieldsRecord.sid: return new ViewFieldsRecord(in); - case DataItemRecord.sid: return new DataItemRecord(in); - case ExtendedPivotTableViewFieldsRecord.sid: return new ExtendedPivotTableViewFieldsRecord(in); - } - return new UnknownRecord(in); - } + // pivot table + case StreamIDRecord.sid: return new StreamIDRecord(in); + case ViewSourceRecord.sid: return new ViewSourceRecord(in); + case PageItemRecord.sid: return new PageItemRecord(in); + case ViewDefinitionRecord.sid: return new ViewDefinitionRecord(in); + case ViewFieldsRecord.sid: return new ViewFieldsRecord(in); + case DataItemRecord.sid: return new DataItemRecord(in); + case ExtendedPivotTableViewFieldsRecord.sid: return new ExtendedPivotTableViewFieldsRecord(in); + } + return new UnknownRecord(in); + } - private static final class CommandArgs { + private static final class CommandArgs { - private final boolean _biffhex; - private final boolean _noint; - private final boolean _out; - private final boolean _rawhex; - private final boolean _noHeader; - private final File _file; + private final boolean _biffhex; + private final boolean _noint; + private final boolean _out; + private final boolean _rawhex; + private final boolean _noHeader; + private final File _file; - private CommandArgs(boolean biffhex, boolean noint, boolean out, boolean rawhex, boolean noHeader, File file) { - _biffhex = biffhex; - _noint = noint; - _out = out; - _rawhex = rawhex; - _file = file; - _noHeader = noHeader; - } + private CommandArgs(boolean biffhex, boolean noint, boolean out, boolean rawhex, boolean noHeader, File file) { + _biffhex = biffhex; + _noint = noint; + _out = out; + _rawhex = rawhex; + _file = file; + _noHeader = noHeader; + } - public static CommandArgs parse(String[] args) throws CommandParseException { - int nArgs = args.length; - boolean biffhex = false; - boolean noint = false; - boolean out = false; - boolean rawhex = false; - boolean noheader = false; - File file = null; - for (int i=0; i entryNames = dir.getEntryNames(); + if (entryNames.contains("Workbook")) { + name = "Workbook"; + } else if (entryNames.contains("WORKBOOK")) { + name = "WORKBOOK"; + } else if (entryNames.contains("BOOK")) { + name = "BOOK"; + } else { + name = "Workbook"; + } - processEvents(req, in); - } + InputStream in = dir.createDocumentInputStream(name); + + processEvents(req, in); + } /** * Processes a file into essentially record events. diff --git a/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java b/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java index 889de20b4..4220ca261 100644 --- a/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java +++ b/src/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +import org.apache.poi.POIDocument; import org.apache.poi.POIOLE2TextExtractor; import org.apache.poi.hpsf.DocumentSummaryInformation; import org.apache.poi.hpsf.SummaryInformation; @@ -75,7 +76,7 @@ public class EventBasedExcelExtractor extends POIOLE2TextExtractor implements or public EventBasedExcelExtractor( DirectoryNode dir ) { - super( null ); + super( (POIDocument)null ); _dir = dir; } @@ -83,16 +84,6 @@ public class EventBasedExcelExtractor extends POIOLE2TextExtractor implements or this(fs.getRoot()); } - /** - * Return the underlying POIFS FileSystem of - * this document. - * - * @deprecated Use {@link #getRoot()} instead - */ - public POIFSFileSystem getFileSystem() { - return _dir.getFileSystem(); - } - /** * Would return the document information metadata for the document, * if we supported it diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java index 3c3b91b14..a2670978e 100644 --- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -774,11 +774,12 @@ public final class InternalWorkbook { } } - // also tell the LinkTable about the removed sheet - // +1 because we already removed it from the count of sheets! - for(int i = sheetIndex+1;i < getNumSheets()+1;i++) { - // also update the link-table as otherwise references might point at invalid sheets - linkTable.removeSheet(i); + if (linkTable != null) { + // also tell the LinkTable about the removed sheet + // +1 because we already removed it from the count of sheets! + for(int i = sheetIndex+1;i < getNumSheets()+1;i++) { + linkTable.removeSheet(i); + } } } diff --git a/src/java/org/apache/poi/hssf/record/CFHeader12Record.java b/src/java/org/apache/poi/hssf/record/CFHeader12Record.java new file mode 100644 index 000000000..89c4421de --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/CFHeader12Record.java @@ -0,0 +1,88 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.hssf.record.common.FtrHeader; +import org.apache.poi.hssf.record.common.FutureRecord; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.util.LittleEndianOutput; + +/** + * Conditional Formatting Header v12 record CFHEADER12 (0x0879), + * for conditional formattings introduced in Excel 2007 and newer. + */ +public final class CFHeader12Record extends CFHeaderBase implements FutureRecord { + public static final short sid = 0x0879; + + private FtrHeader futureHeader; + + /** Creates new CFHeaderRecord */ + public CFHeader12Record() { + createEmpty(); + futureHeader = new FtrHeader(); + futureHeader.setRecordType(sid); + } + public CFHeader12Record(CellRangeAddress[] regions, int nRules) { + super(regions, nRules); + futureHeader = new FtrHeader(); + futureHeader.setRecordType(sid); + } + public CFHeader12Record(RecordInputStream in) { + futureHeader = new FtrHeader(in); + read(in); + } + + @Override + protected String getRecordName() { + return "CFHEADER12"; + } + + protected int getDataSize() { + return FtrHeader.getDataSize() + super.getDataSize(); + } + + public void serialize(LittleEndianOutput out) { + // Sync the associated range + futureHeader.setAssociatedRange(getEnclosingCellRange()); + // Write the future header first + futureHeader.serialize(out); + // Then the rest of the CF Header details + super.serialize(out); + } + + public short getSid() { + return sid; + } + + public short getFutureRecordType() { + return futureHeader.getRecordType(); + } + public FtrHeader getFutureHeader() { + return futureHeader; + } + public CellRangeAddress getAssociatedRange() { + return futureHeader.getAssociatedRange(); + } + + public Object clone() { + CFHeader12Record result = new CFHeader12Record(); + result.futureHeader = (FtrHeader)futureHeader.clone(); + super.copyTo(result); + return result; + } +} diff --git a/src/java/org/apache/poi/hssf/record/CFHeaderBase.java b/src/java/org/apache/poi/hssf/record/CFHeaderBase.java new file mode 100644 index 000000000..4e40a3461 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/CFHeaderBase.java @@ -0,0 +1,153 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record; + +import org.apache.poi.hssf.record.cf.CellRangeUtil; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.util.LittleEndianOutput; + +/** + * Parent of Conditional Formatting Header records, + * {@link CFHeaderRecord} and {@link CFHeader12Record}. + */ +public abstract class CFHeaderBase extends StandardRecord { + private int field_1_numcf; + private int field_2_need_recalculation_and_id; + private CellRangeAddress field_3_enclosing_cell_range; + private CellRangeAddressList field_4_cell_ranges; + + /** Creates new CFHeaderBase */ + protected CFHeaderBase() { + } + protected CFHeaderBase(CellRangeAddress[] regions, int nRules) { + CellRangeAddress[] unmergedRanges = regions; + CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(unmergedRanges); + setCellRanges(mergeCellRanges); + field_1_numcf = nRules; + } + + protected void createEmpty() { + field_3_enclosing_cell_range = new CellRangeAddress(0, 0, 0, 0); + field_4_cell_ranges = new CellRangeAddressList(); + } + protected void read(RecordInputStream in) { + field_1_numcf = in.readShort(); + field_2_need_recalculation_and_id = in.readShort(); + field_3_enclosing_cell_range = new CellRangeAddress(in); + field_4_cell_ranges = new CellRangeAddressList(in); + } + + public int getNumberOfConditionalFormats() { + return field_1_numcf; + } + public void setNumberOfConditionalFormats(int n) { + field_1_numcf=n; + } + + public boolean getNeedRecalculation() { + // Held on the 1st bit + return field_2_need_recalculation_and_id % 2 == 1; + } + public void setNeedRecalculation(boolean b) { + // held on the first bit + if (b == getNeedRecalculation()) return; + if (b) field_2_need_recalculation_and_id++; + else field_2_need_recalculation_and_id--; + } + + public int getID() { + // Remaining 15 bits of field 2 + return field_2_need_recalculation_and_id>>1; + } + public void setID(int id) { + // Remaining 15 bits of field 2 + boolean needsRecalc = getNeedRecalculation(); + field_2_need_recalculation_and_id = (id<<1); + if (needsRecalc) field_2_need_recalculation_and_id++; + } + + public CellRangeAddress getEnclosingCellRange() { + return field_3_enclosing_cell_range; + } + public void setEnclosingCellRange(CellRangeAddress cr) { + field_3_enclosing_cell_range = cr; + } + + /** + * Set cell ranges list to a single cell range and + * modify the enclosing cell range accordingly. + * @param cellRanges - list of CellRange objects + */ + public void setCellRanges(CellRangeAddress[] cellRanges) { + if(cellRanges == null) { + throw new IllegalArgumentException("cellRanges must not be null"); + } + CellRangeAddressList cral = new CellRangeAddressList(); + CellRangeAddress enclosingRange = null; + for (int i = 0; i < cellRanges.length; i++) { + CellRangeAddress cr = cellRanges[i]; + enclosingRange = CellRangeUtil.createEnclosingCellRange(cr, enclosingRange); + cral.addCellRangeAddress(cr); + } + field_3_enclosing_cell_range = enclosingRange; + field_4_cell_ranges = cral; + } + + public CellRangeAddress[] getCellRanges() { + return field_4_cell_ranges.getCellRangeAddresses(); + } + + protected abstract String getRecordName(); + public String toString() { + StringBuffer buffer = new StringBuffer(); + + buffer.append("[").append(getRecordName()).append("]\n"); + buffer.append("\t.numCF = ").append(getNumberOfConditionalFormats()).append("\n"); + buffer.append("\t.needRecalc = ").append(getNeedRecalculation()).append("\n"); + buffer.append("\t.id = ").append(getID()).append("\n"); + buffer.append("\t.enclosingCellRange= ").append(getEnclosingCellRange()).append("\n"); + buffer.append("\t.cfranges=["); + for( int i=0; iThis is for newer-style Excel conditional formattings, + * from Excel 2007 onwards. + * + *

{@link CFRuleRecord} is used where the condition type is + * {@link #CONDITION_TYPE_CELL_VALUE_IS} or {@link #CONDITION_TYPE_FORMULA}, + * this is only used for the other types + */ +public final class CFRule12Record extends CFRuleBase implements FutureRecord { + public static final short sid = 0x087A; + + private FtrHeader futureHeader; + private int ext_formatting_length; + private byte[] ext_formatting_data; + private Formula formula_scale; + private byte ext_opts; + private int priority; + private int template_type; + private byte template_param_length; + private byte[] template_params; + + private IconMultiStateFormatting multistate; + + // TODO Parse these + private byte[] gradient_data; + private byte[] databar_data; + private byte[] filter_data; + + /** Creates new CFRuleRecord */ + private CFRule12Record(byte conditionType, byte comparisonOperation) { + super(conditionType, comparisonOperation); + setDefaults(); + } + + private CFRule12Record(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2, Ptg[] formulaScale) { + super(conditionType, comparisonOperation, formula1, formula2); + setDefaults(); + this.formula_scale = Formula.create(formulaScale); + } + private void setDefaults() { + futureHeader = new FtrHeader(); + futureHeader.setRecordType(sid); + + ext_formatting_length = 0; + ext_formatting_data = new byte[4]; + + formula_scale = Formula.create(Ptg.EMPTY_PTG_ARRAY); + + ext_opts = 0; + priority = 0; + template_type = getConditionType(); + template_param_length = 16; + template_params = new byte[template_param_length]; + } + + /** + * Creates a new comparison operation rule + */ + public static CFRule12Record create(HSSFSheet sheet, String formulaText) { + Ptg[] formula1 = parseFormula(formulaText, sheet); + return new CFRule12Record(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON, + formula1, null, null); + } + /** + * Creates a new comparison operation rule + */ + public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, + String formulaText1, String formulaText2) { + Ptg[] formula1 = parseFormula(formulaText1, sheet); + Ptg[] formula2 = parseFormula(formulaText2, sheet); + return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, + formula1, formula2, null); + } + /** + * Creates a new comparison operation rule + */ + public static CFRule12Record create(HSSFSheet sheet, byte comparisonOperation, + String formulaText1, String formulaText2, String formulaTextScale) { + Ptg[] formula1 = parseFormula(formulaText1, sheet); + Ptg[] formula2 = parseFormula(formulaText2, sheet); + Ptg[] formula3 = parseFormula(formulaTextScale, sheet); + return new CFRule12Record(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, + formula1, formula2, formula3); + } + /** + * Creates a new Icon Set / Multi-State formatting + */ + public static CFRule12Record create(HSSFSheet sheet, IconSet iconSet) { + Threshold[] ts = new Threshold[iconSet.num]; + for (int i=0; iThis is for the older-style Excel conditional formattings, + * new-style (Excel 2007+) also make use of {@link CFRule12Record} + * and {@link CFExRuleRecord} for their rules. + */ +public abstract class CFRuleBase extends StandardRecord { + public static final class ComparisonOperator { + public static final byte NO_COMPARISON = 0; + public static final byte BETWEEN = 1; + public static final byte NOT_BETWEEN = 2; + public static final byte EQUAL = 3; + public static final byte NOT_EQUAL = 4; + public static final byte GT = 5; + public static final byte LT = 6; + public static final byte GE = 7; + public static final byte LE = 8; + private static final byte max_operator = 8; + } + protected static final POILogger logger = POILogFactory.getLogger(CFRuleBase.class); + + private byte condition_type; + // The only kinds that CFRuleRecord handles + public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1; + public static final byte CONDITION_TYPE_FORMULA = 2; + // These are CFRule12Rule only + public static final byte CONDITION_TYPE_COLOR_SCALE = 3; + public static final byte CONDITION_TYPE_DATA_BAR = 4; + public static final byte CONDITION_TYPE_FILTER = 5; + public static final byte CONDITION_TYPE_ICON_SET = 6; + + private byte comparison_operator; + + public static final int TEMPLATE_CELL_VALUE = 0x0000; + public static final int TEMPLATE_FORMULA = 0x0001; + public static final int TEMPLATE_COLOR_SCALE_FORMATTING = 0x0002; + public static final int TEMPLATE_DATA_BAR_FORMATTING = 0x0003; + public static final int TEMPLATE_ICON_SET_FORMATTING = 0x0004; + public static final int TEMPLATE_FILTER = 0x0005; + public static final int TEMPLATE_UNIQUE_VALUES = 0x0007; + public static final int TEMPLATE_CONTAINS_TEXT = 0x0008; + public static final int TEMPLATE_CONTAINS_BLANKS = 0x0009; + public static final int TEMPLATE_CONTAINS_NO_BLANKS = 0x000A; + public static final int TEMPLATE_CONTAINS_ERRORS = 0x000B; + public static final int TEMPLATE_CONTAINS_NO_ERRORS = 0x000C; + public static final int TEMPLATE_TODAY = 0x000F; + public static final int TEMPLATE_TOMORROW = 0x0010; + public static final int TEMPLATE_YESTERDAY = 0x0011; + public static final int TEMPLATE_LAST_7_DAYS = 0x0012; + public static final int TEMPLATE_LAST_MONTH = 0x0013; + public static final int TEMPLATE_NEXT_MONTH = 0x0014; + public static final int TEMPLATE_THIS_WEEK = 0x0015; + public static final int TEMPLATE_NEXT_WEEK = 0x0016; + public static final int TEMPLATE_LAST_WEEK = 0x0017; + public static final int TEMPLATE_THIS_MONTH = 0x0018; + public static final int TEMPLATE_ABOVE_AVERAGE = 0x0019; + public static final int TEMPLATE_BELOW_AVERAGE = 0x001A; + public static final int TEMPLATE_DUPLICATE_VALUES = 0x001B; + public static final int TEMPLATE_ABOVE_OR_EQUAL_TO_AVERAGE = 0x001D; + public static final int TEMPLATE_BELOW_OR_EQUAL_TO_AVERAGE = 0x001E; + + static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot + static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified + static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified + static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified + static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified + static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified + static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified + static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified + static final BitField mergeCell = bf(0x00000080); // Normally 1, 0 = Merge Cell flag modified + static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified + static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified + static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified + static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified + static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified + static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified + static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified + static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified + static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified + static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified + static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified + static final BitField notUsed2 = bf(0x00380000); // Always 111 (ifmt / ifnt / 1) + static final BitField undocumented = bf(0x03C00000); // Undocumented bits + static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot + static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block + static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block + static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block + static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block + static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block + static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified + + private static BitField bf(int i) { + return BitFieldFactory.getInstance(i); + } + + protected int formatting_options; + protected short formatting_not_used; // TODO Decode this properly + + protected FontFormatting _fontFormatting; + protected BorderFormatting _borderFormatting; + protected PatternFormatting _patternFormatting; + + private Formula formula1; + private Formula formula2; + + /** Creates new CFRuleRecord */ + protected CFRuleBase(byte conditionType, byte comparisonOperation) { + setConditionType(conditionType); + setComparisonOperation(comparisonOperation); + formula1 = Formula.create(Ptg.EMPTY_PTG_ARRAY); + formula2 = Formula.create(Ptg.EMPTY_PTG_ARRAY); + } + protected CFRuleBase(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { + this(conditionType, comparisonOperation); + this.formula1 = Formula.create(formula1); + this.formula2 = Formula.create(formula2); + } + protected CFRuleBase() {} + + protected int readFormatOptions(RecordInputStream in) { + formatting_options = in.readInt(); + formatting_not_used = in.readShort(); + + int len = 6; + + if (containsFontFormattingBlock()) { + _fontFormatting = new FontFormatting(in); + len += _fontFormatting.getDataLength(); + } + + if (containsBorderFormattingBlock()) { + _borderFormatting = new BorderFormatting(in); + len += _borderFormatting.getDataLength(); + } + + if (containsPatternFormattingBlock()) { + _patternFormatting = new PatternFormatting(in); + len += _patternFormatting.getDataLength(); + } + + return len; + } + + public byte getConditionType() { + return condition_type; + } + protected void setConditionType(byte condition_type) { + if ((this instanceof CFRuleRecord)) { + if (condition_type == CONDITION_TYPE_CELL_VALUE_IS || + condition_type == CONDITION_TYPE_FORMULA) { + // Good, valid combination + } else { + throw new IllegalArgumentException("CFRuleRecord only accepts Value-Is and Formula types"); + } + } + this.condition_type = condition_type; + } + + public void setComparisonOperation(byte operation) { + if (operation < 0 || operation > ComparisonOperator.max_operator) + throw new IllegalArgumentException( + "Valid operators are only in the range 0 to " +ComparisonOperator.max_operator); + + this.comparison_operator = operation; + } + public byte getComparisonOperation() { + return comparison_operator; + } + + public boolean containsFontFormattingBlock() { + return getOptionFlag(font); + } + public void setFontFormatting(FontFormatting fontFormatting) { + _fontFormatting = fontFormatting; + setOptionFlag(fontFormatting != null, font); + } + public FontFormatting getFontFormatting() { + if( containsFontFormattingBlock()) { + return _fontFormatting; + } + return null; + } + + public boolean containsAlignFormattingBlock() { + return getOptionFlag(align); + } + public void setAlignFormattingUnchanged() { + setOptionFlag(false,align); + } + + public boolean containsBorderFormattingBlock() { + return getOptionFlag(bord); + } + public void setBorderFormatting(BorderFormatting borderFormatting) { + _borderFormatting = borderFormatting; + setOptionFlag(borderFormatting != null, bord); + } + public BorderFormatting getBorderFormatting() { + if( containsBorderFormattingBlock()) { + return _borderFormatting; + } + return null; + } + + public boolean containsPatternFormattingBlock() { + return getOptionFlag(patt); + } + public void setPatternFormatting(PatternFormatting patternFormatting) { + _patternFormatting = patternFormatting; + setOptionFlag(patternFormatting!=null, patt); + } + public PatternFormatting getPatternFormatting() { + if( containsPatternFormattingBlock()) + { + return _patternFormatting; + } + return null; + } + + public boolean containsProtectionFormattingBlock() { + return getOptionFlag(prot); + } + public void setProtectionFormattingUnchanged() { + setOptionFlag(false,prot); + } + + /** + * get the option flags + * + * @return bit mask + */ + public int getOptions() { + return formatting_options; + } + + private boolean isModified(BitField field) { + return !field.isSet(formatting_options); + } + private void setModified(boolean modified, BitField field) { + formatting_options = field.setBoolean(formatting_options, !modified); + } + + public boolean isLeftBorderModified() { + return isModified(bordLeft); + } + public void setLeftBorderModified(boolean modified) { + setModified(modified,bordLeft); + } + + public boolean isRightBorderModified() { + return isModified(bordRight); + } + public void setRightBorderModified(boolean modified) + { + setModified(modified,bordRight); + } + + public boolean isTopBorderModified() { + return isModified(bordTop); + } + public void setTopBorderModified(boolean modified) { + setModified(modified,bordTop); + } + + public boolean isBottomBorderModified() { + return isModified(bordBot); + } + public void setBottomBorderModified(boolean modified) { + setModified(modified,bordBot); + } + + public boolean isTopLeftBottomRightBorderModified() { + return isModified(bordTlBr); + } + public void setTopLeftBottomRightBorderModified(boolean modified) { + setModified(modified,bordTlBr); + } + + public boolean isBottomLeftTopRightBorderModified() { + return isModified(bordBlTr); + } + public void setBottomLeftTopRightBorderModified(boolean modified) { + setModified(modified,bordBlTr); + } + + public boolean isPatternStyleModified() { + return isModified(pattStyle); + } + public void setPatternStyleModified(boolean modified) { + setModified(modified,pattStyle); + } + + public boolean isPatternColorModified() { + return isModified(pattCol); + } + public void setPatternColorModified(boolean modified) { + setModified(modified,pattCol); + } + + public boolean isPatternBackgroundColorModified() { + return isModified(pattBgCol); + } + public void setPatternBackgroundColorModified(boolean modified) { + setModified(modified,pattBgCol); + } + + private boolean getOptionFlag(BitField field) { + return field.isSet(formatting_options); + } + private void setOptionFlag(boolean flag, BitField field) { + formatting_options = field.setBoolean(formatting_options, flag); + } + + protected int getFormattingBlockSize() { + return 6 + + (containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+ + (containsBorderFormattingBlock()?8:0)+ + (containsPatternFormattingBlock()?4:0); + } + protected void serializeFormattingBlock(LittleEndianOutput out) { + out.writeInt(formatting_options); + out.writeShort(formatting_not_used); + + if (containsFontFormattingBlock()) { + byte[] fontFormattingRawRecord = _fontFormatting.getRawRecord(); + out.write(fontFormattingRawRecord); + } + + if (containsBorderFormattingBlock()) { + _borderFormatting.serialize(out); + } + + if (containsPatternFormattingBlock()) { + _patternFormatting.serialize(out); + } + } + + /** + * get the stack of the 1st expression as a list + * + * @return list of tokens (casts stack to a list and returns it!) + * this method can return null is we are unable to create Ptgs from + * existing excel file + * callers should check for null! + */ + public Ptg[] getParsedExpression1() { + return formula1.getTokens(); + } + public void setParsedExpression1(Ptg[] ptgs) { + formula1 = Formula.create(ptgs); + } + protected Formula getFormula1() { + return formula1; + } + protected void setFormula1(Formula formula1) { + this.formula1 = formula1; + } + + /** + * get the stack of the 2nd expression as a list + * + * @return array of {@link Ptg}s, possibly null + */ + public Ptg[] getParsedExpression2() { + return Formula.getTokens(formula2); + } + public void setParsedExpression2(Ptg[] ptgs) { + formula2 = Formula.create(ptgs); + } + protected Formula getFormula2() { + return formula2; + } + protected void setFormula2(Formula formula2) { + this.formula2 = formula2; + } + + /** + * @param formula must not be null + * @return encoded size of the formula tokens (does not include 2 bytes for ushort length) + */ + protected static int getFormulaSize(Formula formula) { + return formula.getEncodedTokenSize(); + } + + /** + * TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea + * this call will produce the wrong results if the formula contains any cell references + * One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int) + * Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects. + * + * @return null if formula was null. + */ + public static Ptg[] parseFormula(String formula, HSSFSheet sheet) { + if(formula == null) { + return null; + } + int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); + return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex); + } + + protected void copyTo(CFRuleBase rec) { + rec.condition_type = condition_type; + rec.comparison_operator = comparison_operator; + + rec.formatting_options = formatting_options; + rec.formatting_not_used = formatting_not_used; + if (containsFontFormattingBlock()) { + rec._fontFormatting = (FontFormatting) _fontFormatting.clone(); + } + if (containsBorderFormattingBlock()) { + rec._borderFormatting = (BorderFormatting) _borderFormatting.clone(); + } + if (containsPatternFormattingBlock()) { + rec._patternFormatting = (PatternFormatting) _patternFormatting.clone(); + } + + rec.setFormula1(getFormula1().copy()); + rec.setFormula2(getFormula2().copy()); + } +} diff --git a/src/java/org/apache/poi/hssf/record/CFRuleRecord.java b/src/java/org/apache/poi/hssf/record/CFRuleRecord.java index 4cf83efce..52678c0fd 100644 --- a/src/java/org/apache/poi/hssf/record/CFRuleRecord.java +++ b/src/java/org/apache/poi/hssf/record/CFRuleRecord.java @@ -19,512 +19,129 @@ package org.apache.poi.hssf.record; import java.util.Arrays; -import org.apache.poi.hssf.model.HSSFFormulaParser; -import org.apache.poi.hssf.record.cf.BorderFormatting; -import org.apache.poi.hssf.record.cf.FontFormatting; -import org.apache.poi.hssf.record.cf.PatternFormatting; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.ss.formula.Formula; -import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.ptg.Ptg; -import org.apache.poi.util.BitField; -import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.LittleEndianOutput; /** - * Conditional Formatting Rule Record (0x01B1).
- * - * @author Dmitriy Kumshayev + * Conditional Formatting Rule Record (0x01B1). + * + *

This is for the older-style Excel conditional formattings, + * new-style (Excel 2007+) also make use of {@link CFRule12Record} + * and {@link CFExRuleRecord} for their rules. */ -public final class CFRuleRecord extends StandardRecord { +public final class CFRuleRecord extends CFRuleBase { + public static final short sid = 0x01B1; - public static final short sid = 0x01B1; + /** Creates new CFRuleRecord */ + private CFRuleRecord(byte conditionType, byte comparisonOperation) { + super(conditionType, comparisonOperation); + setDefaults(); + } - public static final class ComparisonOperator { - public static final byte NO_COMPARISON = 0; - public static final byte BETWEEN = 1; - public static final byte NOT_BETWEEN = 2; - public static final byte EQUAL = 3; - public static final byte NOT_EQUAL = 4; - public static final byte GT = 5; - public static final byte LT = 6; - public static final byte GE = 7; - public static final byte LE = 8; - } + private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { + super(conditionType, comparisonOperation, formula1, formula2); + setDefaults(); + } + private void setDefaults() { + // Set modification flags to 1: by default options are not modified + formatting_options = modificationBits.setValue(formatting_options, -1); + // Set formatting block flags to 0 (no formatting blocks) + formatting_options = fmtBlockBits.setValue(formatting_options, 0); + formatting_options = undocumented.clear(formatting_options); - private byte field_1_condition_type; - public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1; - public static final byte CONDITION_TYPE_FORMULA = 2; + formatting_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads + _fontFormatting = null; + _borderFormatting = null; + _patternFormatting = null; + } - private byte field_2_comparison_operator; - - private int field_5_options; - - private static final BitField modificationBits = bf(0x003FFFFF); // Bits: font,align,bord,patt,prot - private static final BitField alignHor = bf(0x00000001); // 0 = Horizontal alignment modified - private static final BitField alignVer = bf(0x00000002); // 0 = Vertical alignment modified - private static final BitField alignWrap = bf(0x00000004); // 0 = Text wrapped flag modified - private static final BitField alignRot = bf(0x00000008); // 0 = Text rotation modified - private static final BitField alignJustLast = bf(0x00000010); // 0 = Justify last line flag modified - private static final BitField alignIndent = bf(0x00000020); // 0 = Indentation modified - private static final BitField alignShrin = bf(0x00000040); // 0 = Shrink to fit flag modified - private static final BitField notUsed1 = bf(0x00000080); // Always 1 - private static final BitField protLocked = bf(0x00000100); // 0 = Cell locked flag modified - private static final BitField protHidden = bf(0x00000200); // 0 = Cell hidden flag modified - private static final BitField bordLeft = bf(0x00000400); // 0 = Left border style and colour modified - private static final BitField bordRight = bf(0x00000800); // 0 = Right border style and colour modified - private static final BitField bordTop = bf(0x00001000); // 0 = Top border style and colour modified - private static final BitField bordBot = bf(0x00002000); // 0 = Bottom border style and colour modified - private static final BitField bordTlBr = bf(0x00004000); // 0 = Top-left to bottom-right border flag modified - private static final BitField bordBlTr = bf(0x00008000); // 0 = Bottom-left to top-right border flag modified - private static final BitField pattStyle = bf(0x00010000); // 0 = Pattern style modified - private static final BitField pattCol = bf(0x00020000); // 0 = Pattern colour modified - private static final BitField pattBgCol = bf(0x00040000); // 0 = Pattern background colour modified - private static final BitField notUsed2 = bf(0x00380000); // Always 111 - private static final BitField undocumented = bf(0x03C00000); // Undocumented bits - private static final BitField fmtBlockBits = bf(0x7C000000); // Bits: font,align,bord,patt,prot - private static final BitField font = bf(0x04000000); // 1 = Record contains font formatting block - private static final BitField align = bf(0x08000000); // 1 = Record contains alignment formatting block - private static final BitField bord = bf(0x10000000); // 1 = Record contains border formatting block - private static final BitField patt = bf(0x20000000); // 1 = Record contains pattern formatting block - private static final BitField prot = bf(0x40000000); // 1 = Record contains protection formatting block - private static final BitField alignTextDir = bf(0x80000000); // 0 = Text direction modified - - - private static BitField bf(int i) { - return BitFieldFactory.getInstance(i); - } - - private short field_6_not_used; - - private FontFormatting _fontFormatting; - - private BorderFormatting _borderFormatting; - - private PatternFormatting _patternFormatting; - - private Formula field_17_formula1; - private Formula field_18_formula2; - - /** Creates new CFRuleRecord */ - private CFRuleRecord(byte conditionType, byte comparisonOperation) - { - field_1_condition_type=conditionType; - field_2_comparison_operator=comparisonOperation; - - // Set modification flags to 1: by default options are not modified - field_5_options = modificationBits.setValue(field_5_options, -1); - // Set formatting block flags to 0 (no formatting blocks) - field_5_options = fmtBlockBits.setValue(field_5_options, 0); - field_5_options = undocumented.clear(field_5_options); - - field_6_not_used = (short)0x8002; // Excel seems to write this value, but it doesn't seem to care what it reads - _fontFormatting=null; - _borderFormatting=null; - _patternFormatting=null; - field_17_formula1=Formula.create(Ptg.EMPTY_PTG_ARRAY); - field_18_formula2=Formula.create(Ptg.EMPTY_PTG_ARRAY); - } - - private CFRuleRecord(byte conditionType, byte comparisonOperation, Ptg[] formula1, Ptg[] formula2) { - this(conditionType, comparisonOperation); - field_17_formula1 = Formula.create(formula1); - field_18_formula2 = Formula.create(formula2); - } - - /** - * Creates a new comparison operation rule - */ + /** + * Creates a new comparison operation rule + */ public static CFRuleRecord create(HSSFSheet sheet, String formulaText) { Ptg[] formula1 = parseFormula(formulaText, sheet); return new CFRuleRecord(CONDITION_TYPE_FORMULA, ComparisonOperator.NO_COMPARISON, formula1, null); } - /** - * Creates a new comparison operation rule - */ - public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation, - String formulaText1, String formulaText2) { - Ptg[] formula1 = parseFormula(formulaText1, sheet); - Ptg[] formula2 = parseFormula(formulaText2, sheet); - return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2); - } + /** + * Creates a new comparison operation rule + */ + public static CFRuleRecord create(HSSFSheet sheet, byte comparisonOperation, + String formulaText1, String formulaText2) { + Ptg[] formula1 = parseFormula(formulaText1, sheet); + Ptg[] formula2 = parseFormula(formulaText2, sheet); + return new CFRuleRecord(CONDITION_TYPE_CELL_VALUE_IS, comparisonOperation, formula1, formula2); + } - public CFRuleRecord(RecordInputStream in) { - field_1_condition_type = in.readByte(); - field_2_comparison_operator = in.readByte(); - int field_3_formula1_len = in.readUShort(); - int field_4_formula2_len = in.readUShort(); - field_5_options = in.readInt(); - field_6_not_used = in.readShort(); + public CFRuleRecord(RecordInputStream in) { + setConditionType(in.readByte()); + setComparisonOperation(in.readByte()); + int field_3_formula1_len = in.readUShort(); + int field_4_formula2_len = in.readUShort(); + readFormatOptions(in); - if (containsFontFormattingBlock()) { - _fontFormatting = new FontFormatting(in); - } + // "You may not use unions, intersections or array constants in Conditional Formatting criteria" + setFormula1(Formula.read(field_3_formula1_len, in)); + setFormula2(Formula.read(field_4_formula2_len, in)); + } - if (containsBorderFormattingBlock()) { - _borderFormatting = new BorderFormatting(in); - } + public short getSid() { + return sid; + } - if (containsPatternFormattingBlock()) { - _patternFormatting = new PatternFormatting(in); - } + /** + * called by the class that is responsible for writing this sucker. + * Subclasses should implement this so that their data is passed back in a + * byte array. + * + * @param out the stream to write to + */ + public void serialize(LittleEndianOutput out) { + int formula1Len=getFormulaSize(getFormula1()); + int formula2Len=getFormulaSize(getFormula2()); - // "You may not use unions, intersections or array constants in Conditional Formatting criteria" - field_17_formula1 = Formula.read(field_3_formula1_len, in); - field_18_formula2 = Formula.read(field_4_formula2_len, in); - } + out.writeByte(getConditionType()); + out.writeByte(getComparisonOperation()); + out.writeShort(formula1Len); + out.writeShort(formula2Len); + + serializeFormattingBlock(out); - public byte getConditionType() - { - return field_1_condition_type; - } + getFormula1().serializeTokens(out); + getFormula2().serializeTokens(out); + } - public boolean containsFontFormattingBlock() - { - return getOptionFlag(font); - } - public void setFontFormatting(FontFormatting fontFormatting) - { - _fontFormatting = fontFormatting; - setOptionFlag(fontFormatting != null, font); - } - public FontFormatting getFontFormatting() - { - if( containsFontFormattingBlock()) - { - return _fontFormatting; - } - return null; - } + protected int getDataSize() { + return 6 + getFormattingBlockSize() + + getFormulaSize(getFormula1())+ + getFormulaSize(getFormula2()); + } - public boolean containsAlignFormattingBlock() - { - return getOptionFlag(align); - } - public void setAlignFormattingUnchanged() - { - setOptionFlag(false,align); - } - - public boolean containsBorderFormattingBlock() - { - return getOptionFlag(bord); - } - public void setBorderFormatting(BorderFormatting borderFormatting) - { - _borderFormatting = borderFormatting; - setOptionFlag(borderFormatting != null, bord); - } - public BorderFormatting getBorderFormatting() - { - if( containsBorderFormattingBlock()) - { - return _borderFormatting; - } - return null; - } - - public boolean containsPatternFormattingBlock() - { - return getOptionFlag(patt); - } - public void setPatternFormatting(PatternFormatting patternFormatting) - { - _patternFormatting = patternFormatting; - setOptionFlag(patternFormatting!=null, patt); - } - public PatternFormatting getPatternFormatting() - { - if( containsPatternFormattingBlock()) - { - return _patternFormatting; - } - return null; - } - - public boolean containsProtectionFormattingBlock() - { - return getOptionFlag(prot); - } - public void setProtectionFormattingUnchanged() - { - setOptionFlag(false,prot); - } - - public void setComparisonOperation(byte operation) - { - field_2_comparison_operator = operation; - } - - public byte getComparisonOperation() - { - return field_2_comparison_operator; - } - - - /** - * get the option flags - * - * @return bit mask - */ - public int getOptions() - { - return field_5_options; - } - - private boolean isModified(BitField field) - { - return !field.isSet(field_5_options); - } - - private void setModified(boolean modified, BitField field) - { - field_5_options = field.setBoolean(field_5_options, !modified); - } - - public boolean isLeftBorderModified() - { - return isModified(bordLeft); - } - - public void setLeftBorderModified(boolean modified) - { - setModified(modified,bordLeft); - } - - public boolean isRightBorderModified() - { - return isModified(bordRight); - } - - public void setRightBorderModified(boolean modified) - { - setModified(modified,bordRight); - } - - public boolean isTopBorderModified() - { - return isModified(bordTop); - } - - public void setTopBorderModified(boolean modified) - { - setModified(modified,bordTop); - } - - public boolean isBottomBorderModified() - { - return isModified(bordBot); - } - - public void setBottomBorderModified(boolean modified) - { - setModified(modified,bordBot); - } - - public boolean isTopLeftBottomRightBorderModified() - { - return isModified(bordTlBr); - } - - public void setTopLeftBottomRightBorderModified(boolean modified) - { - setModified(modified,bordTlBr); - } - - public boolean isBottomLeftTopRightBorderModified() - { - return isModified(bordBlTr); - } - - public void setBottomLeftTopRightBorderModified(boolean modified) - { - setModified(modified,bordBlTr); - } - - public boolean isPatternStyleModified() - { - return isModified(pattStyle); - } - - public void setPatternStyleModified(boolean modified) - { - setModified(modified,pattStyle); - } - - public boolean isPatternColorModified() - { - return isModified(pattCol); - } - - public void setPatternColorModified(boolean modified) - { - setModified(modified,pattCol); - } - - public boolean isPatternBackgroundColorModified() - { - return isModified(pattBgCol); - } - - public void setPatternBackgroundColorModified(boolean modified) - { - setModified(modified,pattBgCol); - } - - private boolean getOptionFlag(BitField field) - { - return field.isSet(field_5_options); - } - - private void setOptionFlag(boolean flag, BitField field) - { - field_5_options = field.setBoolean(field_5_options, flag); - } - - /** - * get the stack of the 1st expression as a list - * - * @return list of tokens (casts stack to a list and returns it!) - * this method can return null is we are unable to create Ptgs from - * existing excel file - * callers should check for null! - */ - - public Ptg[] getParsedExpression1() - { - return field_17_formula1.getTokens(); - } - public void setParsedExpression1(Ptg[] ptgs) { - field_17_formula1 = Formula.create(ptgs); - } - - /** - * get the stack of the 2nd expression as a list - * - * @return array of {@link Ptg}s, possibly null - */ - public Ptg[] getParsedExpression2() { - return Formula.getTokens(field_18_formula2); - } - public void setParsedExpression2(Ptg[] ptgs) { - field_18_formula2 = Formula.create(ptgs); - } - - public short getSid() - { - return sid; - } - - /** - * @param ptgs must not be null - * @return encoded size of the formula tokens (does not include 2 bytes for ushort length) - */ - private static int getFormulaSize(Formula formula) { - return formula.getEncodedTokenSize(); - } - - /** - * called by the class that is responsible for writing this sucker. - * Subclasses should implement this so that their data is passed back in a - * byte array. - * - * @param out the stream to write to - */ - public void serialize(LittleEndianOutput out) { - - int formula1Len=getFormulaSize(field_17_formula1); - int formula2Len=getFormulaSize(field_18_formula2); - - out.writeByte(field_1_condition_type); - out.writeByte(field_2_comparison_operator); - out.writeShort(formula1Len); - out.writeShort(formula2Len); - out.writeInt(field_5_options); - out.writeShort(field_6_not_used); - - if (containsFontFormattingBlock()) { - byte[] fontFormattingRawRecord = _fontFormatting.getRawRecord(); - out.write(fontFormattingRawRecord); - } - - if (containsBorderFormattingBlock()) { - _borderFormatting.serialize(out); - } - - if (containsPatternFormattingBlock()) { - _patternFormatting.serialize(out); - } - - field_17_formula1.serializeTokens(out); - field_18_formula2.serializeTokens(out); - } - - protected int getDataSize() { - int i = 12 + - (containsFontFormattingBlock()?_fontFormatting.getRawRecord().length:0)+ - (containsBorderFormattingBlock()?8:0)+ - (containsPatternFormattingBlock()?4:0)+ - getFormulaSize(field_17_formula1)+ - getFormulaSize(field_18_formula2); - return i - ; - } - - - public String toString() { - StringBuffer buffer = new StringBuffer(); - buffer.append("[CFRULE]\n"); - buffer.append(" .condition_type =").append(field_1_condition_type).append("\n"); - buffer.append(" OPTION FLAGS=0x").append(Integer.toHexString(getOptions())).append("\n"); - if (containsFontFormattingBlock()) { - buffer.append(_fontFormatting.toString()).append("\n"); - } - if (containsBorderFormattingBlock()) { - buffer.append(_borderFormatting.toString()).append("\n"); - } - if (containsPatternFormattingBlock()) { - buffer.append(_patternFormatting.toString()).append("\n"); - } - buffer.append(" Formula 1 =").append(Arrays.toString(field_17_formula1.getTokens())).append("\n"); - buffer.append(" Formula 2 =").append(Arrays.toString(field_18_formula2.getTokens())).append("\n"); - buffer.append("[/CFRULE]\n"); - return buffer.toString(); - } - - public Object clone() { - CFRuleRecord rec = new CFRuleRecord(field_1_condition_type, field_2_comparison_operator); - rec.field_5_options = field_5_options; - rec.field_6_not_used = field_6_not_used; - if (containsFontFormattingBlock()) { - rec._fontFormatting = (FontFormatting) _fontFormatting.clone(); - } - if (containsBorderFormattingBlock()) { - rec._borderFormatting = (BorderFormatting) _borderFormatting.clone(); - } - if (containsPatternFormattingBlock()) { - rec._patternFormatting = (PatternFormatting) _patternFormatting.clone(); - } - rec.field_17_formula1 = field_17_formula1.copy(); - rec.field_18_formula2 = field_18_formula2.copy(); - - return rec; - } - - /** - * TODO - parse conditional format formulas properly i.e. produce tRefN and tAreaN instead of tRef and tArea - * this call will produce the wrong results if the formula contains any cell references - * One approach might be to apply the inverse of SharedFormulaRecord.convertSharedFormulas(Stack, int, int) - * Note - two extra parameters (rowIx & colIx) will be required. They probably come from one of the Region objects. - * - * @return null if formula was null. - */ - private static Ptg[] parseFormula(String formula, HSSFSheet sheet) { - if(formula == null) { - return null; + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("[CFRULE]\n"); + buffer.append(" .condition_type =").append(getConditionType()).append("\n"); + buffer.append(" OPTION FLAGS=0x").append(Integer.toHexString(getOptions())).append("\n"); + if (containsFontFormattingBlock()) { + buffer.append(_fontFormatting.toString()).append("\n"); } - int sheetIndex = sheet.getWorkbook().getSheetIndex(sheet); - return HSSFFormulaParser.parse(formula, sheet.getWorkbook(), FormulaType.CELL, sheetIndex); + if (containsBorderFormattingBlock()) { + buffer.append(_borderFormatting.toString()).append("\n"); + } + if (containsPatternFormattingBlock()) { + buffer.append(_patternFormatting.toString()).append("\n"); + } + buffer.append(" Formula 1 =").append(Arrays.toString(getFormula1().getTokens())).append("\n"); + buffer.append(" Formula 2 =").append(Arrays.toString(getFormula2().getTokens())).append("\n"); + buffer.append("[/CFRULE]\n"); + return buffer.toString(); + } + + public Object clone() { + CFRuleRecord rec = new CFRuleRecord(getConditionType(), getComparisonOperation()); + super.copyTo(rec); + return rec; } } diff --git a/src/java/org/apache/poi/hssf/record/FeatRecord.java b/src/java/org/apache/poi/hssf/record/FeatRecord.java index 572d6959d..fd583a3d7 100644 --- a/src/java/org/apache/poi/hssf/record/FeatRecord.java +++ b/src/java/org/apache/poi/hssf/record/FeatRecord.java @@ -34,8 +34,11 @@ import org.apache.poi.util.POILogger; * up with a {@link FeatHdrRecord}. */ public final class FeatRecord extends StandardRecord { - private static POILogger logger = POILogFactory.getLogger(FeatRecord.class); - public final static short sid = 0x0868; + private static POILogger logger = POILogFactory.getLogger(FeatRecord.class); + public final static short sid = 0x0868; + // SIDs from newer versions + public final static short v11_sid = 0x0872; + public final static short v12_sid = 0x0878; private FtrHeader futureHeader; diff --git a/src/java/org/apache/poi/hssf/record/NameCommentRecord.java b/src/java/org/apache/poi/hssf/record/NameCommentRecord.java index ed33c2d1f..6b3c8d0bd 100644 --- a/src/java/org/apache/poi/hssf/record/NameCommentRecord.java +++ b/src/java/org/apache/poi/hssf/record/NameCommentRecord.java @@ -62,17 +62,27 @@ public final class NameCommentRecord extends StandardRecord { out.writeShort(field_4_name_length); out.writeShort(field_5_comment_length); - out.writeByte(0); - StringUtil.putCompressedUnicode(field_6_name_text, out); - out.writeByte(0); - StringUtil.putCompressedUnicode(field_7_comment_text, out); + boolean isNameMultiByte = StringUtil.hasMultibyte(field_6_name_text); + out.writeByte(isNameMultiByte ? 1 : 0); + if (isNameMultiByte) { + StringUtil.putUnicodeLE(field_6_name_text, out); + } else { + StringUtil.putCompressedUnicode(field_6_name_text, out); + } + boolean isCommentMultiByte = StringUtil.hasMultibyte(field_7_comment_text); + out.writeByte(isCommentMultiByte ? 1 : 0); + if (isCommentMultiByte) { + StringUtil.putUnicodeLE(field_7_comment_text, out); + } else { + StringUtil.putCompressedUnicode(field_7_comment_text, out); + } } @Override protected int getDataSize() { return 18 // 4 shorts + 1 long + 2 spurious 'nul's - + field_6_name_text.length() - + field_7_comment_text.length(); + + (StringUtil.hasMultibyte(field_6_name_text) ? field_6_name_text.length()*2 : field_6_name_text.length()) + + (StringUtil.hasMultibyte(field_7_comment_text) ? field_7_comment_text.length()*2 : field_7_comment_text.length()); } /** @@ -86,10 +96,16 @@ public final class NameCommentRecord extends StandardRecord { final int field_4_name_length = in.readShort(); final int field_5_comment_length = in.readShort(); - in.readByte(); //spurious NUL - field_6_name_text = StringUtil.readCompressedUnicode(in, field_4_name_length); - in.readByte(); //spurious NUL - field_7_comment_text = StringUtil.readCompressedUnicode(in, field_5_comment_length); + if (in.readByte() == 0) { + field_6_name_text = StringUtil.readCompressedUnicode(in, field_4_name_length); + } else { + field_6_name_text = StringUtil.readUnicodeLE(in, field_4_name_length); + } + if (in.readByte() == 0) { + field_7_comment_text = StringUtil.readCompressedUnicode(in, field_5_comment_length); + } else { + field_7_comment_text = StringUtil.readUnicodeLE(in, field_5_comment_length); + } } /** diff --git a/src/java/org/apache/poi/hssf/record/NameRecord.java b/src/java/org/apache/poi/hssf/record/NameRecord.java index 904133ce6..2f7f81899 100644 --- a/src/java/org/apache/poi/hssf/record/NameRecord.java +++ b/src/java/org/apache/poi/hssf/record/NameRecord.java @@ -411,11 +411,12 @@ public final class NameRecord extends ContinuableRecord { * @return extern sheet index */ public int getExternSheetNumber(){ - if (field_13_name_definition.getEncodedSize() < 1) { + Ptg[] tokens = field_13_name_definition.getTokens(); + if (tokens.length == 0) { return 0; } - Ptg ptg = field_13_name_definition.getTokens()[0]; + Ptg ptg = tokens[0]; if (ptg.getClass() == Area3DPtg.class){ return ((Area3DPtg) ptg).getExternSheetIndex(); diff --git a/src/java/org/apache/poi/hssf/record/RecordFactory.java b/src/java/org/apache/poi/hssf/record/RecordFactory.java index 3a1f7acca..c1a0f5707 100644 --- a/src/java/org/apache/poi/hssf/record/RecordFactory.java +++ b/src/java/org/apache/poi/hssf/record/RecordFactory.java @@ -62,425 +62,420 @@ import org.apache.poi.hssf.record.pivottable.ViewSourceRecord; * Description: Takes a stream and outputs an array of Record objects.

* * @see org.apache.poi.hssf.eventmodel.EventRecordFactory - * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Marc Johnson (mjohnson at apache dot org) - * @author Glen Stampoultzis (glens at apache.org) - * @author Csaba Nagy (ncsaba at yahoo dot com) */ public final class RecordFactory { - private static final int NUM_RECORDS = 512; + private static final int NUM_RECORDS = 512; - private interface I_RecordCreator { - Record create(RecordInputStream in); + private interface I_RecordCreator { + Record create(RecordInputStream in); - Class getRecordClass(); - } - private static final class ReflectionConstructorRecordCreator implements I_RecordCreator { + Class getRecordClass(); + } + private static final class ReflectionConstructorRecordCreator implements I_RecordCreator { - private final Constructor _c; - public ReflectionConstructorRecordCreator(Constructor c) { - _c = c; - } - public Record create(RecordInputStream in) { - Object[] args = { in, }; - try { - return _c.newInstance(args); - } catch (IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (InstantiationException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - Throwable t = e.getTargetException(); - if (t instanceof RecordFormatException) { - throw (RecordFormatException)t; - } else if (t instanceof EncryptedDocumentException) { - throw (EncryptedDocumentException)t; - } else { - throw new RecordFormatException("Unable to construct record instance" , t); - } - } - } - public Class getRecordClass() { - return _c.getDeclaringClass(); - } - } - /** - * A "create" method is used instead of the usual constructor if the created record might - * be of a different class to the declaring class. - */ - private static final class ReflectionMethodRecordCreator implements I_RecordCreator { + private final Constructor _c; + public ReflectionConstructorRecordCreator(Constructor c) { + _c = c; + } + public Record create(RecordInputStream in) { + Object[] args = { in, }; + try { + return _c.newInstance(args); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + if (t instanceof RecordFormatException) { + throw (RecordFormatException)t; + } else if (t instanceof EncryptedDocumentException) { + throw (EncryptedDocumentException)t; + } else { + throw new RecordFormatException("Unable to construct record instance" , t); + } + } + } + public Class getRecordClass() { + return _c.getDeclaringClass(); + } + } + /** + * A "create" method is used instead of the usual constructor if the created record might + * be of a different class to the declaring class. + */ + private static final class ReflectionMethodRecordCreator implements I_RecordCreator { + private final Method _m; + public ReflectionMethodRecordCreator(Method m) { + _m = m; + } + public Record create(RecordInputStream in) { + Object[] args = { in, }; + try { + return (Record) _m.invoke(null, args); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RecordFormatException("Unable to construct record instance" , e.getTargetException()); + } + } + @SuppressWarnings("unchecked") + public Class getRecordClass() { + return (Class) _m.getDeclaringClass(); + } + } - private final Method _m; - public ReflectionMethodRecordCreator(Method m) { - _m = m; - } - public Record create(RecordInputStream in) { - Object[] args = { in, }; - try { - return (Record) _m.invoke(null, args); - } catch (IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw new RecordFormatException("Unable to construct record instance" , e.getTargetException()); - } - } - @SuppressWarnings("unchecked") - public Class getRecordClass() { - return (Class) _m.getDeclaringClass(); - } - } + private static final Class[] CONSTRUCTOR_ARGS = { RecordInputStream.class, }; - - private static final Class[] CONSTRUCTOR_ARGS = { RecordInputStream.class, }; - - /** - * contains the classes for all the records we want to parse.
- * Note - this most but not *every* subclass of Record. - */ - @SuppressWarnings("unchecked") - private static final Class[] recordClasses = new Class[] { - ArrayRecord.class, + /** + * contains the classes for all the records we want to parse.
+ * Note - this most but not *every* subclass of Record. + */ + @SuppressWarnings("unchecked") + private static final Class[] recordClasses = new Class[] { + ArrayRecord.class, AutoFilterInfoRecord.class, BackupRecord.class, - BlankRecord.class, - BOFRecord.class, - BookBoolRecord.class, - BoolErrRecord.class, - BottomMarginRecord.class, - BoundSheetRecord.class, - CalcCountRecord.class, - CalcModeRecord.class, - CFHeaderRecord.class, - CFRuleRecord.class, - ChartRecord.class, - ChartTitleFormatRecord.class, - CodepageRecord.class, - ColumnInfoRecord.class, - ContinueRecord.class, - CountryRecord.class, - CRNCountRecord.class, - CRNRecord.class, - DateWindow1904Record.class, - DBCellRecord.class, - DConRefRecord.class, - DefaultColWidthRecord.class, - DefaultRowHeightRecord.class, - DeltaRecord.class, - DimensionsRecord.class, - DrawingGroupRecord.class, - DrawingRecord.class, - DrawingSelectionRecord.class, - DSFRecord.class, - DVALRecord.class, - DVRecord.class, - EOFRecord.class, - ExtendedFormatRecord.class, - ExternalNameRecord.class, - ExternSheetRecord.class, - ExtSSTRecord.class, - FeatRecord.class, - FeatHdrRecord.class, - FilePassRecord.class, - FileSharingRecord.class, - FnGroupCountRecord.class, - FontRecord.class, - FooterRecord.class, - FormatRecord.class, - FormulaRecord.class, - GridsetRecord.class, - GutsRecord.class, - HCenterRecord.class, - HeaderRecord.class, + BlankRecord.class, + BOFRecord.class, + BookBoolRecord.class, + BoolErrRecord.class, + BottomMarginRecord.class, + BoundSheetRecord.class, + CalcCountRecord.class, + CalcModeRecord.class, + CFHeaderRecord.class, + CFHeader12Record.class, + CFRuleRecord.class, + CFRule12Record.class, + ChartRecord.class, + ChartTitleFormatRecord.class, + CodepageRecord.class, + ColumnInfoRecord.class, + ContinueRecord.class, + CountryRecord.class, + CRNCountRecord.class, + CRNRecord.class, + DateWindow1904Record.class, + DBCellRecord.class, + DConRefRecord.class, + DefaultColWidthRecord.class, + DefaultRowHeightRecord.class, + DeltaRecord.class, + DimensionsRecord.class, + DrawingGroupRecord.class, + DrawingRecord.class, + DrawingSelectionRecord.class, + DSFRecord.class, + DVALRecord.class, + DVRecord.class, + EOFRecord.class, + ExtendedFormatRecord.class, + ExternalNameRecord.class, + ExternSheetRecord.class, + ExtSSTRecord.class, + FeatRecord.class, + FeatHdrRecord.class, + FilePassRecord.class, + FileSharingRecord.class, + FnGroupCountRecord.class, + FontRecord.class, + FooterRecord.class, + FormatRecord.class, + FormulaRecord.class, + GridsetRecord.class, + GutsRecord.class, + HCenterRecord.class, + HeaderRecord.class, HeaderFooterRecord.class, - HideObjRecord.class, - HorizontalPageBreakRecord.class, - HyperlinkRecord.class, - IndexRecord.class, - InterfaceEndRecord.class, - InterfaceHdrRecord.class, - IterationRecord.class, - LabelRecord.class, - LabelSSTRecord.class, - LeftMarginRecord.class, - LegendRecord.class, - MergeCellsRecord.class, - MMSRecord.class, - MulBlankRecord.class, - MulRKRecord.class, - NameRecord.class, - NameCommentRecord.class, - NoteRecord.class, - NumberRecord.class, - ObjectProtectRecord.class, - ObjRecord.class, - PaletteRecord.class, - PaneRecord.class, - PasswordRecord.class, - PasswordRev4Record.class, - PrecisionRecord.class, - PrintGridlinesRecord.class, - PrintHeadersRecord.class, - PrintSetupRecord.class, - ProtectionRev4Record.class, - ProtectRecord.class, - RecalcIdRecord.class, - RefModeRecord.class, - RefreshAllRecord.class, - RightMarginRecord.class, - RKRecord.class, - RowRecord.class, - SaveRecalcRecord.class, - ScenarioProtectRecord.class, - SelectionRecord.class, - SeriesRecord.class, - SeriesTextRecord.class, - SharedFormulaRecord.class, - SSTRecord.class, - StringRecord.class, - StyleRecord.class, - SupBookRecord.class, - TabIdRecord.class, - TableRecord.class, - TableStylesRecord.class, - TextObjectRecord.class, - TopMarginRecord.class, - UncalcedRecord.class, - UseSelFSRecord.class, - UserSViewBegin.class, - UserSViewEnd.class, - ValueRangeRecord.class, - VCenterRecord.class, - VerticalPageBreakRecord.class, - WindowOneRecord.class, - WindowProtectRecord.class, - WindowTwoRecord.class, - WriteAccessRecord.class, - WriteProtectRecord.class, - WSBoolRecord.class, + HideObjRecord.class, + HorizontalPageBreakRecord.class, + HyperlinkRecord.class, + IndexRecord.class, + InterfaceEndRecord.class, + InterfaceHdrRecord.class, + IterationRecord.class, + LabelRecord.class, + LabelSSTRecord.class, + LeftMarginRecord.class, + LegendRecord.class, + MergeCellsRecord.class, + MMSRecord.class, + MulBlankRecord.class, + MulRKRecord.class, + NameRecord.class, + NameCommentRecord.class, + NoteRecord.class, + NumberRecord.class, + ObjectProtectRecord.class, + ObjRecord.class, + PaletteRecord.class, + PaneRecord.class, + PasswordRecord.class, + PasswordRev4Record.class, + PrecisionRecord.class, + PrintGridlinesRecord.class, + PrintHeadersRecord.class, + PrintSetupRecord.class, + ProtectionRev4Record.class, + ProtectRecord.class, + RecalcIdRecord.class, + RefModeRecord.class, + RefreshAllRecord.class, + RightMarginRecord.class, + RKRecord.class, + RowRecord.class, + SaveRecalcRecord.class, + ScenarioProtectRecord.class, + SelectionRecord.class, + SeriesRecord.class, + SeriesTextRecord.class, + SharedFormulaRecord.class, + SSTRecord.class, + StringRecord.class, + StyleRecord.class, + SupBookRecord.class, + TabIdRecord.class, + TableRecord.class, + TableStylesRecord.class, + TextObjectRecord.class, + TopMarginRecord.class, + UncalcedRecord.class, + UseSelFSRecord.class, + UserSViewBegin.class, + UserSViewEnd.class, + ValueRangeRecord.class, + VCenterRecord.class, + VerticalPageBreakRecord.class, + WindowOneRecord.class, + WindowProtectRecord.class, + WindowTwoRecord.class, + WriteAccessRecord.class, + WriteProtectRecord.class, + WSBoolRecord.class, - // chart records - BeginRecord.class, - ChartFRTInfoRecord.class, - ChartStartBlockRecord.class, - ChartEndBlockRecord.class, -// TODO ChartFormatRecord.class, - ChartStartObjectRecord.class, - ChartEndObjectRecord.class, - CatLabRecord.class, - DataFormatRecord.class, - EndRecord.class, - LinkedDataRecord.class, - SeriesToChartGroupRecord.class, + // chart records + BeginRecord.class, + ChartFRTInfoRecord.class, + ChartStartBlockRecord.class, + ChartEndBlockRecord.class, + // TODO ChartFormatRecord.class, + ChartStartObjectRecord.class, + ChartEndObjectRecord.class, + CatLabRecord.class, + DataFormatRecord.class, + EndRecord.class, + LinkedDataRecord.class, + SeriesToChartGroupRecord.class, - // pivot table records - DataItemRecord.class, - ExtendedPivotTableViewFieldsRecord.class, - PageItemRecord.class, - StreamIDRecord.class, - ViewDefinitionRecord.class, - ViewFieldsRecord.class, - ViewSourceRecord.class, - }; + // pivot table records + DataItemRecord.class, + ExtendedPivotTableViewFieldsRecord.class, + PageItemRecord.class, + StreamIDRecord.class, + ViewDefinitionRecord.class, + ViewFieldsRecord.class, + ViewSourceRecord.class, + }; - /** - * cache of the recordsToMap(); - */ - private static final Map _recordCreatorsById = recordsToMap(recordClasses); + /** + * cache of the recordsToMap(); + */ + private static final Map _recordCreatorsById = recordsToMap(recordClasses); - private static short[] _allKnownRecordSIDs; + private static short[] _allKnownRecordSIDs; - /** - * Debug / diagnosis method
- * Gets the POI implementation class for a given sid. Only a subset of the any BIFF - * records are actually interpreted by POI. A few others are known but not interpreted - * (see {@link UnknownRecord#getBiffName(int)}). - * @return the POI implementation class for the specified record sid. - * null if the specified record is not interpreted by POI. - */ - public static Class getRecordClass(int sid) { - I_RecordCreator rc = _recordCreatorsById.get(Integer.valueOf(sid)); - if (rc == null) { - return null; - } - return rc.getRecordClass(); - } - /** - * create a record, if there are MUL records than multiple records - * are returned digested into the non-mul form. - */ - public static Record [] createRecord(RecordInputStream in) { + /** + * Debug / diagnosis method
+ * Gets the POI implementation class for a given sid. Only a subset of the any BIFF + * records are actually interpreted by POI. A few others are known but not interpreted + * (see {@link UnknownRecord#getBiffName(int)}). + * @return the POI implementation class for the specified record sid. + * null if the specified record is not interpreted by POI. + */ + public static Class getRecordClass(int sid) { + I_RecordCreator rc = _recordCreatorsById.get(Integer.valueOf(sid)); + if (rc == null) { + return null; + } + return rc.getRecordClass(); + } + /** + * create a record, if there are MUL records than multiple records + * are returned digested into the non-mul form. + */ + public static Record [] createRecord(RecordInputStream in) { + Record record = createSingleRecord(in); + if (record instanceof DBCellRecord) { + // Not needed by POI. Regenerated from scratch by POI when spreadsheet is written + return new Record[] { null, }; + } + if (record instanceof RKRecord) { + return new Record[] { convertToNumberRecord((RKRecord) record), }; + } + if (record instanceof MulRKRecord) { + return convertRKRecords((MulRKRecord)record); + } + return new Record[] { record, }; + } - Record record = createSingleRecord(in); - if (record instanceof DBCellRecord) { - // Not needed by POI. Regenerated from scratch by POI when spreadsheet is written - return new Record[] { null, }; - } - if (record instanceof RKRecord) { - return new Record[] { convertToNumberRecord((RKRecord) record), }; - } - if (record instanceof MulRKRecord) { - return convertRKRecords((MulRKRecord)record); - } - return new Record[] { record, }; - } + public static Record createSingleRecord(RecordInputStream in) { + I_RecordCreator constructor = _recordCreatorsById.get(Integer.valueOf(in.getSid())); - public static Record createSingleRecord(RecordInputStream in) { - I_RecordCreator constructor = _recordCreatorsById.get(Integer.valueOf(in.getSid())); + if (constructor == null) { + return new UnknownRecord(in); + } - if (constructor == null) { - return new UnknownRecord(in); - } + return constructor.create(in); + } - return constructor.create(in); - } + /** + * RK record is a slightly smaller alternative to NumberRecord + * POI likes NumberRecord better + */ + public static NumberRecord convertToNumberRecord(RKRecord rk) { + NumberRecord num = new NumberRecord(); - /** - * RK record is a slightly smaller alternative to NumberRecord - * POI likes NumberRecord better - */ - public static NumberRecord convertToNumberRecord(RKRecord rk) { - NumberRecord num = new NumberRecord(); + num.setColumn(rk.getColumn()); + num.setRow(rk.getRow()); + num.setXFIndex(rk.getXFIndex()); + num.setValue(rk.getRKNumber()); + return num; + } - num.setColumn(rk.getColumn()); - num.setRow(rk.getRow()); - num.setXFIndex(rk.getXFIndex()); - num.setValue(rk.getRKNumber()); - return num; - } + /** + * Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s + */ + public static NumberRecord[] convertRKRecords(MulRKRecord mrk) { + NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()]; + for (int k = 0; k < mrk.getNumColumns(); k++) { + NumberRecord nr = new NumberRecord(); - /** - * Converts a {@link MulRKRecord} into an equivalent array of {@link NumberRecord}s - */ - public static NumberRecord[] convertRKRecords(MulRKRecord mrk) { - NumberRecord[] mulRecs = new NumberRecord[mrk.getNumColumns()]; - for (int k = 0; k < mrk.getNumColumns(); k++) { - NumberRecord nr = new NumberRecord(); + nr.setColumn((short) (k + mrk.getFirstColumn())); + nr.setRow(mrk.getRow()); + nr.setXFIndex(mrk.getXFAt(k)); + nr.setValue(mrk.getRKNumberAt(k)); + mulRecs[k] = nr; + } + return mulRecs; + } - nr.setColumn((short) (k + mrk.getFirstColumn())); - nr.setRow(mrk.getRow()); - nr.setXFIndex(mrk.getXFAt(k)); - nr.setValue(mrk.getRKNumberAt(k)); - mulRecs[k] = nr; - } - return mulRecs; - } + /** + * Converts a {@link MulBlankRecord} into an equivalent array of {@link BlankRecord}s + */ + public static BlankRecord[] convertBlankRecords(MulBlankRecord mbk) { + BlankRecord[] mulRecs = new BlankRecord[mbk.getNumColumns()]; + for (int k = 0; k < mbk.getNumColumns(); k++) { + BlankRecord br = new BlankRecord(); - /** - * Converts a {@link MulBlankRecord} into an equivalent array of {@link BlankRecord}s - */ - public static BlankRecord[] convertBlankRecords(MulBlankRecord mbk) { - BlankRecord[] mulRecs = new BlankRecord[mbk.getNumColumns()]; - for (int k = 0; k < mbk.getNumColumns(); k++) { - BlankRecord br = new BlankRecord(); + br.setColumn((short) (k + mbk.getFirstColumn())); + br.setRow(mbk.getRow()); + br.setXFIndex(mbk.getXFAt(k)); + mulRecs[k] = br; + } + return mulRecs; + } - br.setColumn((short) (k + mbk.getFirstColumn())); - br.setRow(mbk.getRow()); - br.setXFIndex(mbk.getXFAt(k)); - mulRecs[k] = br; - } - return mulRecs; - } + /** + * @return an array of all the SIDS for all known records + */ + public static short[] getAllKnownRecordSIDs() { + if (_allKnownRecordSIDs == null) { + short[] results = new short[ _recordCreatorsById.size() ]; + int i = 0; - /** - * @return an array of all the SIDS for all known records - */ - public static short[] getAllKnownRecordSIDs() { - if (_allKnownRecordSIDs == null) { - short[] results = new short[ _recordCreatorsById.size() ]; - int i = 0; + for (Iterator iterator = _recordCreatorsById.keySet().iterator(); iterator.hasNext(); ) { + Integer sid = iterator.next(); - for (Iterator iterator = _recordCreatorsById.keySet().iterator(); iterator.hasNext(); ) { - Integer sid = iterator.next(); + results[i++] = sid.shortValue(); + } + Arrays.sort(results); + _allKnownRecordSIDs = results; + } - results[i++] = sid.shortValue(); - } - Arrays.sort(results); - _allKnownRecordSIDs = results; - } + return _allKnownRecordSIDs.clone(); + } - return _allKnownRecordSIDs.clone(); - } + /** + * gets the record constructors and sticks them in the map by SID + * @return map of SIDs to short,short,byte[] constructors for Record classes + * most of org.apache.poi.hssf.record.* + */ + private static Map recordsToMap(Class [] records) { + Map result = new HashMap(); + Set> uniqueRecClasses = new HashSet>(records.length * 3 / 2); - /** - * gets the record constructors and sticks them in the map by SID - * @return map of SIDs to short,short,byte[] constructors for Record classes - * most of org.apache.poi.hssf.record.* - */ - private static Map recordsToMap(Class [] records) { - Map result = new HashMap(); - Set> uniqueRecClasses = new HashSet>(records.length * 3 / 2); + for (int i = 0; i < records.length; i++) { - for (int i = 0; i < records.length; i++) { + Class recClass = records[ i ]; + if(!Record.class.isAssignableFrom(recClass)) { + throw new RuntimeException("Invalid record sub-class (" + recClass.getName() + ")"); + } + if(Modifier.isAbstract(recClass.getModifiers())) { + throw new RuntimeException("Invalid record class (" + recClass.getName() + ") - must not be abstract"); + } + if(!uniqueRecClasses.add(recClass)) { + throw new RuntimeException("duplicate record class (" + recClass.getName() + ")"); + } - Class recClass = records[ i ]; - if(!Record.class.isAssignableFrom(recClass)) { - throw new RuntimeException("Invalid record sub-class (" + recClass.getName() + ")"); - } - if(Modifier.isAbstract(recClass.getModifiers())) { - throw new RuntimeException("Invalid record class (" + recClass.getName() + ") - must not be abstract"); - } - if(!uniqueRecClasses.add(recClass)) { - throw new RuntimeException("duplicate record class (" + recClass.getName() + ")"); - } + int sid; + try { + sid = recClass.getField("sid").getShort(null); + } catch (Exception illegalArgumentException) { + throw new RecordFormatException( + "Unable to determine record types"); + } + Integer key = Integer.valueOf(sid); + if (result.containsKey(key)) { + Class prevClass = result.get(key).getRecordClass(); + throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase() + + " for classes (" + recClass.getName() + ") and (" + prevClass.getName() + ")"); + } + result.put(key, getRecordCreator(recClass)); + } + // result.put(Integer.valueOf(0x0406), result.get(Integer.valueOf(0x06))); + return result; + } - int sid; - try { - sid = recClass.getField("sid").getShort(null); - } catch (Exception illegalArgumentException) { - throw new RecordFormatException( - "Unable to determine record types"); - } - Integer key = Integer.valueOf(sid); - if (result.containsKey(key)) { - Class prevClass = result.get(key).getRecordClass(); - throw new RuntimeException("duplicate record sid 0x" + Integer.toHexString(sid).toUpperCase() - + " for classes (" + recClass.getName() + ") and (" + prevClass.getName() + ")"); - } - result.put(key, getRecordCreator(recClass)); - } -// result.put(Integer.valueOf(0x0406), result.get(Integer.valueOf(0x06))); - return result; - } + private static I_RecordCreator getRecordCreator(Class recClass) { + try { + Constructor constructor; + constructor = recClass.getConstructor(CONSTRUCTOR_ARGS); + return new ReflectionConstructorRecordCreator(constructor); + } catch (NoSuchMethodException e) { + // fall through and look for other construction methods + } + try { + Method m = recClass.getDeclaredMethod("create", CONSTRUCTOR_ARGS); + return new ReflectionMethodRecordCreator(m); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Failed to find constructor or create method for (" + recClass.getName() + ")."); + } + } + /** + * Create an array of records from an input stream + * + * @param in the InputStream from which the records will be obtained + * + * @return an array of Records created from the InputStream + * + * @exception RecordFormatException on error processing the InputStream + */ + public static List createRecords(InputStream in) throws RecordFormatException { - private static I_RecordCreator getRecordCreator(Class recClass) { - try { - Constructor constructor; - constructor = recClass.getConstructor(CONSTRUCTOR_ARGS); - return new ReflectionConstructorRecordCreator(constructor); - } catch (NoSuchMethodException e) { - // fall through and look for other construction methods - } - try { - Method m = recClass.getDeclaredMethod("create", CONSTRUCTOR_ARGS); - return new ReflectionMethodRecordCreator(m); - } catch (NoSuchMethodException e) { - throw new RuntimeException("Failed to find constructor or create method for (" + recClass.getName() + ")."); - } - } - /** - * Create an array of records from an input stream - * - * @param in the InputStream from which the records will be obtained - * - * @return an array of Records created from the InputStream - * - * @exception RecordFormatException on error processing the InputStream - */ - public static List createRecords(InputStream in) throws RecordFormatException { + List records = new ArrayList(NUM_RECORDS); - List records = new ArrayList(NUM_RECORDS); + RecordFactoryInputStream recStream = new RecordFactoryInputStream(in, true); - RecordFactoryInputStream recStream = new RecordFactoryInputStream(in, true); + Record record; + while ((record = recStream.nextRecord())!=null) { + records.add(record); + } - Record record; - while ((record = recStream.nextRecord())!=null) { - records.add(record); - } - - return records; - } + return records; + } } diff --git a/src/java/org/apache/poi/hssf/record/RecordInputStream.java b/src/java/org/apache/poi/hssf/record/RecordInputStream.java index 9f0b16e18..9de7d6889 100644 --- a/src/java/org/apache/poi/hssf/record/RecordInputStream.java +++ b/src/java/org/apache/poi/hssf/record/RecordInputStream.java @@ -52,8 +52,17 @@ public final class RecordInputStream implements LittleEndianInput { public static final class LeftoverDataException extends RuntimeException { public LeftoverDataException(int sid, int remainingByteCount) { super("Initialisation of record 0x" + Integer.toHexString(sid).toUpperCase() - + " left " + remainingByteCount + " bytes remaining still to be read."); + + "(" + getRecordName(sid) + ") left " + remainingByteCount + + " bytes remaining still to be read."); } + + private static String getRecordName(int sid) { + Class recordClass = RecordFactory.getRecordClass(sid); + if(recordClass == null) { + return null; + } + return recordClass.getSimpleName(); + } } /** Header {@link LittleEndianInput} facet of the wrapped {@link InputStream} */ diff --git a/src/java/org/apache/poi/hssf/record/RowRecord.java b/src/java/org/apache/poi/hssf/record/RowRecord.java index 75d3f99b1..ffbf9c753 100644 --- a/src/java/org/apache/poi/hssf/record/RowRecord.java +++ b/src/java/org/apache/poi/hssf/record/RowRecord.java @@ -64,6 +64,9 @@ public final class RowRecord extends StandardRecord { // bit 15 is unused public RowRecord(int rowNumber) { + if(rowNumber < 0) { + throw new IllegalArgumentException("Invalid row number (" + rowNumber + ")"); + } field_1_row_number = rowNumber; field_4_height = (short)0xFF; field_5_optimize = ( short ) 0; @@ -76,6 +79,9 @@ public final class RowRecord extends StandardRecord { public RowRecord(RecordInputStream in) { field_1_row_number = in.readUShort(); + if(field_1_row_number < 0) { + throw new IllegalArgumentException("Invalid row number " + field_1_row_number + " found in InputStream"); + } field_2_first_col = in.readShort(); field_3_last_col = in.readShort(); field_4_height = in.readShort(); diff --git a/src/java/org/apache/poi/hssf/record/UnknownRecord.java b/src/java/org/apache/poi/hssf/record/UnknownRecord.java index 6b46247e2..f87953aba 100644 --- a/src/java/org/apache/poi/hssf/record/UnknownRecord.java +++ b/src/java/org/apache/poi/hssf/record/UnknownRecord.java @@ -179,8 +179,10 @@ public final class UnknownRecord extends StandardRecord { case SHEETPROTECTION_0867: return "SHEETPROTECTION"; case 0x086B: return "DATALABEXTCONTENTS"; case 0x086C: return "CELLWATCH"; + case FeatRecord.v11_sid: return "SHARED FEATURE v11"; case 0x0874: return "DROPDOWNOBJIDS"; case 0x0876: return "DCONN"; + case FeatRecord.v12_sid: return "SHARED FEATURE v12"; case 0x087B: return "CFEX"; case 0x087C: return "XFCRC"; case 0x087D: return "XFEXT"; @@ -194,15 +196,21 @@ public final class UnknownRecord extends StandardRecord { case 0x089A: return "MTRSETTINGS"; case 0x089B: return "COMPRESSPICTURES"; case HEADER_FOOTER_089C: return "HEADERFOOTER"; + case 0x089D: return "CRTLAYOUT12"; + case 0x089E: return "CRTMLFRT"; + case 0x089F: return "CRTMLFRTCONTINUE"; case 0x08A1: return "SHAPEPROPSSTREAM"; case 0x08A3: return "FORCEFULLCALCULATION"; case 0x08A4: return "SHAPEPROPSSTREAM"; case 0x08A5: return "TEXTPROPSSTREAM"; case 0x08A6: return "RICHTEXTSTREAM"; + case 0x08A7: return "CRTLAYOUT12A"; case 0x08C8: return "PLV{Mac Excel}"; - - + + case 0x1001: return "UNITS"; + case 0x1006: return "CHARTDATAFORMAT"; + case 0x1007: return "CHARTLINEFORMAT"; } if (isObservedButUnknown(sid)) { return "UNKNOWN-" + Integer.toHexString(sid).toUpperCase(); @@ -215,6 +223,7 @@ public final class UnknownRecord extends StandardRecord { * @return true if the unknown record id has been observed in POI unit tests */ private static boolean isObservedButUnknown(int sid) { + // TODO Look up more of these in the latest [MS-XLS] doc and move to getBiffName switch (sid) { case 0x0033: // contains 2 bytes of data: 0x0001 or 0x0003 @@ -227,13 +236,7 @@ public final class UnknownRecord extends StandardRecord { // Written by Excel 2007 // rawData is multiple of 12 bytes long // appears after last cell value record and before WINDOW2 or drawing records - case 0x089D: - case 0x089E: - case 0x08A7: - case 0x1001: - case 0x1006: - case 0x1007: case 0x1009: case 0x100A: case 0x100B: diff --git a/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java index d9d64123a..c43e4f5ae 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/CFRecordsAggregate.java @@ -21,7 +21,11 @@ import java.util.ArrayList; import java.util.List; import org.apache.poi.hssf.model.RecordStream; +import org.apache.poi.hssf.record.CFHeader12Record; +import org.apache.poi.hssf.record.CFHeaderBase; import org.apache.poi.hssf.record.CFHeaderRecord; +import org.apache.poi.hssf.record.CFRule12Record; +import org.apache.poi.hssf.record.CFRuleBase; import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.ss.formula.FormulaShifter; @@ -38,212 +42,240 @@ import org.apache.poi.util.POILogger; *

Note that Excel versions before 2007 can only cope with a maximum of 3 * Conditional Formatting rules per sheet. Excel 2007 or newer can cope with * unlimited numbers, as can Apache OpenOffice. This is an Excel limitation, - * not a file format one.

+ * not a file format one.

*/ public final class CFRecordsAggregate extends RecordAggregate { - /** Excel 97-2003 allows up to 3 conditional formating rules */ - private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3; - private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class); + /** Excel 97-2003 allows up to 3 conditional formating rules */ + private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3; + private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class); - private final CFHeaderRecord header; + private final CFHeaderBase header; - /** List of CFRuleRecord objects */ - private final List rules; + /** List of CFRuleRecord objects */ + private final List rules; - private CFRecordsAggregate(CFHeaderRecord pHeader, CFRuleRecord[] pRules) { - if(pHeader == null) { - throw new IllegalArgumentException("header must not be null"); - } - if(pRules == null) { - throw new IllegalArgumentException("rules must not be null"); - } - if(pRules.length > MAX_97_2003_CONDTIONAL_FORMAT_RULES) { - logger.log(POILogger.WARN, "Excel versions before 2007 require that " - + "No more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES - + " rules may be specified, " + pRules.length + " were found," - + " this file will cause problems with old Excel versions"); - } - if (pRules.length != pHeader.getNumberOfConditionalFormats()) { - throw new RuntimeException("Mismatch number of rules"); - } - header = pHeader; - rules = new ArrayList(3); - for (int i = 0; i < pRules.length; i++) { - rules.add(pRules[i]); - } - } + private CFRecordsAggregate(CFHeaderBase pHeader, CFRuleBase[] pRules) { + if(pHeader == null) { + throw new IllegalArgumentException("header must not be null"); + } + if(pRules == null) { + throw new IllegalArgumentException("rules must not be null"); + } + if(pRules.length > MAX_97_2003_CONDTIONAL_FORMAT_RULES) { + logger.log(POILogger.WARN, "Excel versions before 2007 require that " + + "No more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES + + " rules may be specified, " + pRules.length + " were found," + + " this file will cause problems with old Excel versions"); + } + if (pRules.length != pHeader.getNumberOfConditionalFormats()) { + throw new RuntimeException("Mismatch number of rules"); + } + header = pHeader; + rules = new ArrayList(pRules.length); + for (int i = 0; i < pRules.length; i++) { + checkRuleType(pRules[i]); + rules.add(pRules[i]); + } + } - public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleRecord[] rules) { - this(new CFHeaderRecord(regions, rules.length), rules); - } + public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleBase[] rules) { + this(createHeader(regions, rules), rules); + } + private static CFHeaderBase createHeader(CellRangeAddress[] regions, CFRuleBase[] rules) { + if (rules.length == 0 || rules[0] instanceof CFRuleRecord) { + return new CFHeaderRecord(regions, rules.length); + } + return new CFHeader12Record(regions, rules.length); + } - /** - * Create CFRecordsAggregate from a list of CF Records - * @param rs - the stream to read from - * @return CFRecordsAggregate object - */ - public static CFRecordsAggregate createCFAggregate(RecordStream rs) { - Record rec = rs.getNext(); - if (rec.getSid() != CFHeaderRecord.sid) { - throw new IllegalStateException("next record sid was " + rec.getSid() - + " instead of " + CFHeaderRecord.sid + " as expected"); - } + /** + * Create CFRecordsAggregate from a list of CF Records + * @param rs - the stream to read from + * @return CFRecordsAggregate object + */ + public static CFRecordsAggregate createCFAggregate(RecordStream rs) { + Record rec = rs.getNext(); + if (rec.getSid() != CFHeaderRecord.sid && + rec.getSid() != CFHeader12Record.sid) { + throw new IllegalStateException("next record sid was " + rec.getSid() + + " instead of " + CFHeaderRecord.sid + " or " + + CFHeader12Record.sid + " as expected"); + } - CFHeaderRecord header = (CFHeaderRecord)rec; - int nRules = header.getNumberOfConditionalFormats(); + CFHeaderBase header = (CFHeaderBase)rec; + int nRules = header.getNumberOfConditionalFormats(); - CFRuleRecord[] rules = new CFRuleRecord[nRules]; - for (int i = 0; i < rules.length; i++) { - rules[i] = (CFRuleRecord) rs.getNext(); - } - - return new CFRecordsAggregate(header, rules); - } + CFRuleBase[] rules = new CFRuleBase[nRules]; + for (int i = 0; i < rules.length; i++) { + rules[i] = (CFRuleBase) rs.getNext(); + } - /** - * Create a deep clone of the record - */ - public CFRecordsAggregate cloneCFAggregate() - { - - CFRuleRecord[] newRecs = new CFRuleRecord[rules.size()]; - for (int i = 0; i < newRecs.length; i++) { - newRecs[i] = (CFRuleRecord) getRule(i).clone(); - } - return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs); - } + return new CFRecordsAggregate(header, rules); + } - /** - * @return the header. Never null. - */ - public CFHeaderRecord getHeader() - { - return header; - } - - private void checkRuleIndex(int idx) { - if(idx < 0 || idx >= rules.size()) { - throw new IllegalArgumentException("Bad rule record index (" + idx - + ") nRules=" + rules.size()); - } - } - public CFRuleRecord getRule(int idx) { - checkRuleIndex(idx); - return rules.get(idx); - } - public void setRule(int idx, CFRuleRecord r) { - if (r == null) { - throw new IllegalArgumentException("r must not be null"); - } - checkRuleIndex(idx); - rules.set(idx, r); - } - public void addRule(CFRuleRecord r) { - if (r == null) { - throw new IllegalArgumentException("r must not be null"); - } - if(rules.size() >= MAX_97_2003_CONDTIONAL_FORMAT_RULES) { + /** + * Create a deep clone of the record + */ + public CFRecordsAggregate cloneCFAggregate() { + CFRuleBase[] newRecs = new CFRuleBase[rules.size()]; + for (int i = 0; i < newRecs.length; i++) { + newRecs[i] = (CFRuleRecord) getRule(i).clone(); + } + return new CFRecordsAggregate((CFHeaderBase)header.clone(), newRecs); + } + + /** + * @return the header. Never null. + */ + public CFHeaderBase getHeader() { + return header; + } + + private void checkRuleIndex(int idx) { + if(idx < 0 || idx >= rules.size()) { + throw new IllegalArgumentException("Bad rule record index (" + idx + + ") nRules=" + rules.size()); + } + } + private void checkRuleType(CFRuleBase r) { + if (header instanceof CFHeaderRecord && + r instanceof CFRuleRecord) { + return; + } + if (header instanceof CFHeader12Record && + r instanceof CFRule12Record) { + return; + } + throw new IllegalArgumentException("Header and Rule must both be CF or both be CF12, can't mix"); + } + + public CFRuleBase getRule(int idx) { + checkRuleIndex(idx); + return rules.get(idx); + } + public void setRule(int idx, CFRuleBase r) { + if (r == null) { + throw new IllegalArgumentException("r must not be null"); + } + checkRuleIndex(idx); + checkRuleType(r); + rules.set(idx, r); + } + public void addRule(CFRuleBase r) { + if (r == null) { + throw new IllegalArgumentException("r must not be null"); + } + if(rules.size() >= MAX_97_2003_CONDTIONAL_FORMAT_RULES) { logger.log(POILogger.WARN, "Excel versions before 2007 cannot cope with" - + " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES + + " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES + " - this file will cause problems with old Excel versions"); - } - rules.add(r); - header.setNumberOfConditionalFormats(rules.size()); - } - public int getNumberOfRules() { - return rules.size(); - } + } + checkRuleType(r); + rules.add(r); + header.setNumberOfConditionalFormats(rules.size()); + } + public int getNumberOfRules() { + return rules.size(); + } - /** - * String representation of CFRecordsAggregate - */ - public String toString() - { - StringBuffer buffer = new StringBuffer(); + /** + * String representation of CFRecordsAggregate + */ + public String toString() { + StringBuffer buffer = new StringBuffer(); + String type = "CF"; + if (header instanceof CFHeader12Record) { + type = "CF12"; + } - buffer.append("[CF]\n"); - if( header != null ) - { - buffer.append(header.toString()); - } - for(int i=0; ifalse if this whole {@link CFHeaderRecord} / {@link CFRuleRecord}s should be deleted - */ - public boolean updateFormulasAfterCellShift(FormulaShifter shifter, int currentExternSheetIx) { - CellRangeAddress[] cellRanges = header.getCellRanges(); - boolean changed = false; - List temp = new ArrayList(); - for (int i = 0; i < cellRanges.length; i++) { - CellRangeAddress craOld = cellRanges[i]; - CellRangeAddress craNew = shiftRange(shifter, craOld, currentExternSheetIx); - if (craNew == null) { - changed = true; - continue; - } - temp.add(craNew); - if (craNew != craOld) { - changed = true; - } - } + /** + * @return false if this whole {@link CFHeaderRecord} / {@link CFRuleRecord}s should be deleted + */ + public boolean updateFormulasAfterCellShift(FormulaShifter shifter, int currentExternSheetIx) { + CellRangeAddress[] cellRanges = header.getCellRanges(); + boolean changed = false; + List temp = new ArrayList(); + for (int i = 0; i < cellRanges.length; i++) { + CellRangeAddress craOld = cellRanges[i]; + CellRangeAddress craNew = shiftRange(shifter, craOld, currentExternSheetIx); + if (craNew == null) { + changed = true; + continue; + } + temp.add(craNew); + if (craNew != craOld) { + changed = true; + } + } - if (changed) { - int nRanges = temp.size(); - if (nRanges == 0) { - return false; - } - CellRangeAddress[] newRanges = new CellRangeAddress[nRanges]; - temp.toArray(newRanges); - header.setCellRanges(newRanges); - } - - for(int i=0; i * * See OOO exelfileformat.pdf sec 4.12 'Conditional Formatting Table' - * - * @author Josh Micich */ public final class ConditionalFormattingTable extends RecordAggregate { - private final List _cfHeaders; /** @@ -45,7 +43,8 @@ public final class ConditionalFormattingTable extends RecordAggregate { public ConditionalFormattingTable(RecordStream rs) { List temp = new ArrayList(); - while (rs.peekNextClass() == CFHeaderRecord.class) { + while (rs.peekNextClass() == CFHeaderRecord.class || + rs.peekNextClass() == CFHeader12Record.class) { temp.add(CFRecordsAggregate.createCFAggregate(rs)); } _cfHeaders = temp; @@ -62,6 +61,7 @@ public final class ConditionalFormattingTable extends RecordAggregate { * @return index of the newly added CF header aggregate */ public int add(CFRecordsAggregate cfAggregate) { + cfAggregate.getHeader().setID(_cfHeaders.size()); _cfHeaders.add(cfAggregate); return _cfHeaders.size() - 1; } diff --git a/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java b/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java index e9eca9925..ef003d536 100644 --- a/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/BorderFormatting.java @@ -25,11 +25,8 @@ import org.apache.poi.util.LittleEndianOutput; /** * Border Formatting Block of the Conditional Formatting Rule Record. - * - * @author Dmitriy Kumshayev */ public final class BorderFormatting { - /** No border */ public final static short BORDER_NONE = 0x0; /** Thin border */ @@ -89,6 +86,9 @@ public final class BorderFormatting { field_14_border_styles2 = in.readInt(); } + public int getDataLength() { + return 8; + } /** * set the type of border to use for the left border of the cell diff --git a/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java b/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java index d1532a94d..cde666a8e 100644 --- a/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java +++ b/src/java/org/apache/poi/hssf/record/cf/CellRangeUtil.java @@ -23,97 +23,93 @@ import java.util.List; import org.apache.poi.ss.util.CellRangeAddress; /** - * - * @author Dmitriy Kumshayev + * TODO Should this move to org.apache.poi.ss.util ? */ -public final class CellRangeUtil -{ - - private CellRangeUtil() { - // no instance of this class - } - - public static final int NO_INTERSECTION = 1; - public static final int OVERLAP = 2; - /** first range is within the second range */ - public static final int INSIDE = 3; - /** first range encloses or is equal to the second */ - public static final int ENCLOSES = 4; - - /** - * Intersect this range with the specified range. - * - * @param crB - the specified range - * @return code which reflects how the specified range is related to this range.
- * Possible return codes are: - * NO_INTERSECTION - the specified range is outside of this range;
- * OVERLAP - both ranges partially overlap;
- * INSIDE - the specified range is inside of this one
- * ENCLOSES - the specified range encloses (possibly exactly the same as) this range
- */ - public static int intersect(CellRangeAddress crA, CellRangeAddress crB ) - { - - int firstRow = crB.getFirstRow(); - int lastRow = crB.getLastRow(); - int firstCol = crB.getFirstColumn(); - int lastCol = crB.getLastColumn(); - - if - ( +public final class CellRangeUtil { + private CellRangeUtil() { + // no instance of this class + } + + public static final int NO_INTERSECTION = 1; + public static final int OVERLAP = 2; + /** first range is within the second range */ + public static final int INSIDE = 3; + /** first range encloses or is equal to the second */ + public static final int ENCLOSES = 4; + + /** + * Intersect this range with the specified range. + * + * @param crB - the specified range + * @return code which reflects how the specified range is related to this range.
+ * Possible return codes are: + * NO_INTERSECTION - the specified range is outside of this range;
+ * OVERLAP - both ranges partially overlap;
+ * INSIDE - the specified range is inside of this one
+ * ENCLOSES - the specified range encloses (possibly exactly the same as) this range
+ */ + public static int intersect(CellRangeAddress crA, CellRangeAddress crB ) + { + + int firstRow = crB.getFirstRow(); + int lastRow = crB.getLastRow(); + int firstCol = crB.getFirstColumn(); + int lastCol = crB.getLastColumn(); + + if + ( gt(crA.getFirstRow(),lastRow) || lt(crA.getLastRow(),firstRow) || gt(crA.getFirstColumn(),lastCol) || lt(crA.getLastColumn(),firstCol) - ) - { - return NO_INTERSECTION; - } - else if( contains(crA, crB) ) - { - return INSIDE; - } - else if( contains(crB, crA)) - { - return ENCLOSES; - } - else - { - return OVERLAP; - } - - } - - /** - * Do all possible cell merges between cells of the list so that:
- *
  • if a cell range is completely inside of another cell range, it gets removed from the list - *
  • if two cells have a shared border, merge them into one bigger cell range - * @param cellRanges - * @return updated List of cell ranges - */ - public static CellRangeAddress[] mergeCellRanges(CellRangeAddress[] cellRanges) { - if(cellRanges.length < 1) { - return cellRanges; - } + ) + { + return NO_INTERSECTION; + } + else if( contains(crA, crB) ) + { + return INSIDE; + } + else if( contains(crB, crA)) + { + return ENCLOSES; + } + else + { + return OVERLAP; + } + } + + /** + * Do all possible cell merges between cells of the list so that:
    + *
  • if a cell range is completely inside of another cell range, it gets removed from the list + *
  • if two cells have a shared border, merge them into one bigger cell range + * @param cellRanges + * @return updated List of cell ranges + */ + public static CellRangeAddress[] mergeCellRanges(CellRangeAddress[] cellRanges) { + if(cellRanges.length < 1) { + return cellRanges; + } List lst = new ArrayList(); for(CellRangeAddress cr : cellRanges) { lst.add(cr); } List temp = mergeCellRanges(lst); - return toArray(temp); - } + return toArray(temp); + } - private static List mergeCellRanges(List cellRangeList) - { - // loop until either only one item is left or we did not merge anything any more + private static List mergeCellRanges(List cellRangeList) + { + // loop until either only one item is left or we did not merge anything any more while (cellRangeList.size() > 1) { boolean somethingGotMerged = false; // look at all cell-ranges for (int i = 0; i < cellRangeList.size(); i++) { CellRangeAddress range1 = cellRangeList.get(i); - + // compare each cell range to all other cell-ranges for (int j = i + 1; j < cellRangeList.size(); j++) { CellRangeAddress range2 = cellRangeList.get(j); @@ -139,16 +135,16 @@ public final class CellRangeUtil } } - return cellRangeList; - } - - /** - * @return the new range(s) to replace the supplied ones. null if no merge is possible - */ - private static CellRangeAddress[] mergeRanges(CellRangeAddress range1, CellRangeAddress range2) { - int x = intersect(range1, range2); - switch(x) - { + return cellRangeList; + } + + /** + * @return the new range(s) to replace the supplied ones. null if no merge is possible + */ + private static CellRangeAddress[] mergeRanges(CellRangeAddress range1, CellRangeAddress range2) { + int x = intersect(range1, range2); + switch(x) + { case CellRangeUtil.NO_INTERSECTION: // nothing in common: at most they could be adjacent to each other and thus form a single bigger area if(hasExactSharedBorder(range1, range2)) { @@ -171,108 +167,103 @@ public final class CellRangeUtil throw new RuntimeException("unexpected intersection result (" + x + ")"); } - - private static CellRangeAddress[] toArray(List temp) { - CellRangeAddress[] result = new CellRangeAddress[temp.size()]; - temp.toArray(result); - return result; - } + private static CellRangeAddress[] toArray(List temp) { + CellRangeAddress[] result = new CellRangeAddress[temp.size()]; + temp.toArray(result); + return result; + } + /** + * Check if the specified range is located inside of this cell range. + * + * @param crB + * @return true if this cell range contains the argument range inside if it's area + */ + public static boolean contains(CellRangeAddress crA, CellRangeAddress crB) + { + int firstRow = crB.getFirstRow(); + int lastRow = crB.getLastRow(); + int firstCol = crB.getFirstColumn(); + int lastCol = crB.getLastColumn(); + return le(crA.getFirstRow(), firstRow) && ge(crA.getLastRow(), lastRow) + && le(crA.getFirstColumn(), firstCol) && ge(crA.getLastColumn(), lastCol); + } + /** + * Check if the two cell ranges have a shared border. + * + * @return true if the ranges have a complete shared border (i.e. + * the two ranges together make a simple rectangular region. + */ + public static boolean hasExactSharedBorder(CellRangeAddress crA, CellRangeAddress crB) { + int oFirstRow = crB.getFirstRow(); + int oLastRow = crB.getLastRow(); + int oFirstCol = crB.getFirstColumn(); + int oLastCol = crB.getLastColumn(); - /** - * Check if the specified range is located inside of this cell range. - * - * @param crB - * @return true if this cell range contains the argument range inside if it's area - */ - public static boolean contains(CellRangeAddress crA, CellRangeAddress crB) - { - int firstRow = crB.getFirstRow(); - int lastRow = crB.getLastRow(); - int firstCol = crB.getFirstColumn(); - int lastCol = crB.getLastColumn(); - return le(crA.getFirstRow(), firstRow) && ge(crA.getLastRow(), lastRow) - && le(crA.getFirstColumn(), firstCol) && ge(crA.getLastColumn(), lastCol); - } - - /** - * Check if the two cell ranges have a shared border. - * - * @return true if the ranges have a complete shared border (i.e. - * the two ranges together make a simple rectangular region. - */ - public static boolean hasExactSharedBorder(CellRangeAddress crA, CellRangeAddress crB) { - int oFirstRow = crB.getFirstRow(); - int oLastRow = crB.getLastRow(); - int oFirstCol = crB.getFirstColumn(); - int oLastCol = crB.getLastColumn(); - - if (crA.getFirstRow() > 0 && crA.getFirstRow()-1 == oLastRow || - oFirstRow > 0 && oFirstRow-1 == crA.getLastRow()) { - // ranges have a horizontal border in common - // make sure columns are identical: - return crA.getFirstColumn() == oFirstCol && crA.getLastColumn() == oLastCol; - } + if (crA.getFirstRow() > 0 && crA.getFirstRow()-1 == oLastRow || + oFirstRow > 0 && oFirstRow-1 == crA.getLastRow()) { + // ranges have a horizontal border in common + // make sure columns are identical: + return crA.getFirstColumn() == oFirstCol && crA.getLastColumn() == oLastCol; + } - if (crA.getFirstColumn()>0 && crA.getFirstColumn() - 1 == oLastCol || - oFirstCol>0 && crA.getLastColumn() == oFirstCol -1) { - // ranges have a vertical border in common - // make sure rows are identical: - return crA.getFirstRow() == oFirstRow && crA.getLastRow() == oLastRow; - } - return false; - } - - /** - * Create an enclosing CellRange for the two cell ranges. - * - * @return enclosing CellRange - */ - public static CellRangeAddress createEnclosingCellRange(CellRangeAddress crA, CellRangeAddress crB) { - if( crB == null) { - return crA.copy(); - } - - return - new CellRangeAddress( - lt(crB.getFirstRow(), crA.getFirstRow()) ?crB.getFirstRow() :crA.getFirstRow(), - gt(crB.getLastRow(), crA.getLastRow()) ?crB.getLastRow() :crA.getLastRow(), - lt(crB.getFirstColumn(),crA.getFirstColumn())?crB.getFirstColumn():crA.getFirstColumn(), - gt(crB.getLastColumn(), crA.getLastColumn()) ?crB.getLastColumn() :crA.getLastColumn() - ); - - } - - /** - * @return true if a < b - */ - private static boolean lt(int a, int b) - { - return a == -1 ? false : (b == -1 ? true : a < b); - } - - /** - * @return true if a <= b - */ - private static boolean le(int a, int b) - { - return a == b || lt(a,b); - } - - /** - * @return true if a > b - */ - private static boolean gt(int a, int b) - { - return lt(b,a); - } + if (crA.getFirstColumn()>0 && crA.getFirstColumn() - 1 == oLastCol || + oFirstCol>0 && crA.getLastColumn() == oFirstCol -1) { + // ranges have a vertical border in common + // make sure rows are identical: + return crA.getFirstRow() == oFirstRow && crA.getLastRow() == oLastRow; + } + return false; + } - /** - * @return true if a >= b - */ - private static boolean ge(int a, int b) - { - return !lt(a,b); - } + /** + * Create an enclosing CellRange for the two cell ranges. + * + * @return enclosing CellRange + */ + public static CellRangeAddress createEnclosingCellRange(CellRangeAddress crA, CellRangeAddress crB) { + if( crB == null) { + return crA.copy(); + } + + return new CellRangeAddress( + lt(crB.getFirstRow(), crA.getFirstRow()) ?crB.getFirstRow() :crA.getFirstRow(), + gt(crB.getLastRow(), crA.getLastRow()) ?crB.getLastRow() :crA.getLastRow(), + lt(crB.getFirstColumn(),crA.getFirstColumn())?crB.getFirstColumn():crA.getFirstColumn(), + gt(crB.getLastColumn(), crA.getLastColumn()) ?crB.getLastColumn() :crA.getLastColumn() + ); + } + + /** + * @return true if a < b + */ + private static boolean lt(int a, int b) + { + return a == -1 ? false : (b == -1 ? true : a < b); + } + + /** + * @return true if a <= b + */ + private static boolean le(int a, int b) + { + return a == b || lt(a,b); + } + + /** + * @return true if a > b + */ + private static boolean gt(int a, int b) + { + return lt(b,a); + } + + /** + * @return true if a >= b + */ + private static boolean ge(int a, int b) + { + return !lt(a,b); + } } diff --git a/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java index be7aafac0..59c49d8a4 100644 --- a/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java +++ b/src/java/org/apache/poi/hssf/record/cf/FontFormatting.java @@ -25,525 +25,523 @@ import org.apache.poi.util.LittleEndian; /** * Font Formatting Block of the Conditional Formatting Rule Record. - * - * @author Dmitriy Kumshayev */ -public final class FontFormatting -{ - private byte[] _rawData; - - private static final int OFFSET_FONT_NAME = 0; - private static final int OFFSET_FONT_HEIGHT = 64; - private static final int OFFSET_FONT_OPTIONS = 68; - private static final int OFFSET_FONT_WEIGHT = 72; - private static final int OFFSET_ESCAPEMENT_TYPE = 74; - private static final int OFFSET_UNDERLINE_TYPE = 76; - private static final int OFFSET_FONT_COLOR_INDEX = 80; - private static final int OFFSET_OPTION_FLAGS = 88; - private static final int OFFSET_ESCAPEMENT_TYPE_MODIFIED = 92; - private static final int OFFSET_UNDERLINE_TYPE_MODIFIED = 96; - private static final int OFFSET_FONT_WEIGHT_MODIFIED = 100; - private static final int OFFSET_NOT_USED1 = 104; - private static final int OFFSET_NOT_USED2 = 108; - private static final int OFFSET_NOT_USED3 = 112; // for some reason Excel always writes 0x7FFFFFFF at this offset - private static final int OFFSET_FONT_FORMATING_END = 116; - private static final int RAW_DATA_SIZE = 118; - - - public final static int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF; - - // FONT OPTIONS MASKS - private static final BitField posture = BitFieldFactory.getInstance(0x00000002); - private static final BitField outline = BitFieldFactory.getInstance(0x00000008); - private static final BitField shadow = BitFieldFactory.getInstance(0x00000010); - private static final BitField cancellation = BitFieldFactory.getInstance(0x00000080); - - // OPTION FLAGS MASKS - - private static final BitField styleModified = BitFieldFactory.getInstance(0x00000002); - private static final BitField outlineModified = BitFieldFactory.getInstance(0x00000008); - private static final BitField shadowModified = BitFieldFactory.getInstance(0x00000010); - private static final BitField cancellationModified = BitFieldFactory.getInstance(0x00000080); - - /** Escapement type - None */ - public static final short SS_NONE = 0; - /** Escapement type - Superscript */ - public static final short SS_SUPER = 1; - /** Escapement type - Subscript */ - public static final short SS_SUB = 2; - /** Underline type - None */ - public static final byte U_NONE = 0; - /** Underline type - Single */ - public static final byte U_SINGLE = 1; - /** Underline type - Double */ - public static final byte U_DOUBLE = 2; - /** Underline type - Single Accounting */ - public static final byte U_SINGLE_ACCOUNTING = 0x21; - /** Underline type - Double Accounting */ - public static final byte U_DOUBLE_ACCOUNTING = 0x22; - /** Normal boldness (not bold) */ - private static final short FONT_WEIGHT_NORMAL = 0x190; - - /** - * Bold boldness (bold) - */ - private static final short FONT_WEIGHT_BOLD = 0x2bc; - - private FontFormatting(byte[] rawData) { - _rawData = rawData; - } - - public FontFormatting() - { - this(new byte[RAW_DATA_SIZE]); - - setFontHeight(-1); - setItalic(false); - setFontWieghtModified(false); - setOutline(false); - setShadow(false); - setStrikeout(false); - setEscapementType((short)0); - setUnderlineType((byte)0); - setFontColorIndex((short)-1); - - setFontStyleModified(false); - setFontOutlineModified(false); - setFontShadowModified(false); - setFontCancellationModified(false); - - setEscapementTypeModified(false); - setUnderlineTypeModified(false); - - setShort(OFFSET_FONT_NAME, 0); - setInt(OFFSET_NOT_USED1, 0x00000001); - setInt(OFFSET_NOT_USED2, 0x00000000); - setInt(OFFSET_NOT_USED3, 0x7FFFFFFF);// for some reason Excel always writes 0x7FFFFFFF at this offset - setShort(OFFSET_FONT_FORMATING_END, 0x0001); - } - - /** Creates new FontFormatting */ - public FontFormatting(RecordInputStream in) - { - this(new byte[RAW_DATA_SIZE]); - for (int i = 0; i < _rawData.length; i++) - { - _rawData[i] = in.readByte(); - } - } - - private short getShort(int offset) { - return LittleEndian.getShort( _rawData, offset); - } - private void setShort(int offset, int value) { - LittleEndian.putShort( _rawData, offset, (short)value); - } - private int getInt(int offset) { - return LittleEndian.getInt( _rawData, offset); - } - private void setInt(int offset, int value) { - LittleEndian.putInt( _rawData, offset, value); - } - - public byte[] getRawRecord() - { - return _rawData; - } - - /** - * sets the height of the font in 1/20th point units - * - * - * @param height fontheight (in points/20); or -1 to preserve the cell font height - */ - - public void setFontHeight(int height) - { - setInt(OFFSET_FONT_HEIGHT, height); - } - - /** - * gets the height of the font in 1/20th point units - * - * @return fontheight (in points/20); or -1 if not modified - */ - public int getFontHeight() - { - return getInt(OFFSET_FONT_HEIGHT); - } - - private void setFontOption(boolean option, BitField field) - { - int options = getInt(OFFSET_FONT_OPTIONS); - options = field.setBoolean(options, option); - setInt(OFFSET_FONT_OPTIONS, options); - } - - private boolean getFontOption(BitField field) - { - int options = getInt(OFFSET_FONT_OPTIONS); - return field.isSet(options); - } - - /** - * set the font to be italics or not - * - * @param italic - whether the font is italics or not - * @see #setFontOption(boolean, org.apache.poi.util.BitField) - */ - - public void setItalic(boolean italic) - { - setFontOption(italic, posture); - } - - /** - * get whether the font is to be italics or not - * - * @return italics - whether the font is italics or not - * @see #getFontOption(org.apache.poi.util.BitField) - */ - - public boolean isItalic() - { - return getFontOption(posture); - } - - public void setOutline(boolean on) - { - setFontOption(on, outline); - } - - public boolean isOutlineOn() - { - return getFontOption(outline); - } - - public void setShadow(boolean on) - { - setFontOption(on, shadow); - } - - public boolean isShadowOn() - { - return getFontOption(shadow); - } - - /** - * set the font to be stricken out or not - * - * @param strike - whether the font is stricken out or not - */ - - public void setStrikeout(boolean strike) - { - setFontOption(strike, cancellation); - } - - /** - * get whether the font is to be stricken out or not - * - * @return strike - whether the font is stricken out or not - * @see #getFontOption(org.apache.poi.util.BitField) - */ - - public boolean isStruckout() - { - return getFontOption(cancellation); - } - - /** - * set the font weight (100-1000dec or 0x64-0x3e8). Default is - * 0x190 for normal and 0x2bc for bold - * - * @param bw - a number between 100-1000 for the fonts "boldness" - */ - - private void setFontWeight(short pbw) - { - short bw = pbw; - if( bw<100) { bw=100; } - if( bw>1000){ bw=1000; } - setShort(OFFSET_FONT_WEIGHT, bw); - } - - /** - * set the font weight to bold (weight=700) or to normal(weight=400) boldness. - * - * @param bold - set font weight to bold if true; to normal otherwise - */ - public void setBold(boolean bold) - { - setFontWeight(bold?FONT_WEIGHT_BOLD:FONT_WEIGHT_NORMAL); - } - - /** - * get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is - * 0x190 for normal and 0x2bc for bold - * - * @return bw - a number between 100-1000 for the fonts "boldness" - */ - - public short getFontWeight() - { - return getShort(OFFSET_FONT_WEIGHT); - } - - /** - * get whether the font weight is set to bold or not - * - * @return bold - whether the font is bold or not - */ - - public boolean isBold() - { - return getFontWeight()==FONT_WEIGHT_BOLD; - } - - /** - * get the type of super or subscript for the font - * - * @return super or subscript option - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_NONE - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUPER - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUB - */ - public short getEscapementType() - { - return getShort(OFFSET_ESCAPEMENT_TYPE); - } - - /** - * set the escapement type for the font - * - * @param escapementType super or subscript option - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_NONE - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUPER - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUB - */ - public void setEscapementType( short escapementType) - { - setShort(OFFSET_ESCAPEMENT_TYPE, escapementType); - } - - /** - * get the type of underlining for the font - * - * @return font underlining type - * - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE_ACCOUNTING - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE_ACCOUNTING - */ - - public short getUnderlineType() - { - return getShort(OFFSET_UNDERLINE_TYPE); - } - - /** - * set the type of underlining type for the font - * - * @param underlineType underline option - * - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE_ACCOUNTING - * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE_ACCOUNTING - */ - public void setUnderlineType( short underlineType) - { - setShort(OFFSET_UNDERLINE_TYPE, underlineType); - } - - - public short getFontColorIndex() - { - return (short)getInt(OFFSET_FONT_COLOR_INDEX); - } - - public void setFontColorIndex(short fci ) - { - setInt(OFFSET_FONT_COLOR_INDEX,fci); - } - - private boolean getOptionFlag(BitField field) - { - int optionFlags = getInt(OFFSET_OPTION_FLAGS); - int value = field.getValue(optionFlags); - return value==0? true : false ; - } - - private void setOptionFlag(boolean modified, BitField field) - { - int value = modified? 0 : 1; - int optionFlags = getInt(OFFSET_OPTION_FLAGS); - optionFlags = field.setValue(optionFlags, value); - setInt(OFFSET_OPTION_FLAGS, optionFlags); - } - - - public boolean isFontStyleModified() - { - return getOptionFlag(styleModified); - } - - - public void setFontStyleModified(boolean modified) - { - setOptionFlag(modified, styleModified); - } - - public boolean isFontOutlineModified() - { - return getOptionFlag(outlineModified); - } - - public void setFontOutlineModified(boolean modified) - { - setOptionFlag(modified, outlineModified); - } - - public boolean isFontShadowModified() - { - return getOptionFlag(shadowModified); - } - - public void setFontShadowModified(boolean modified) - { - setOptionFlag(modified, shadowModified); - } - public void setFontCancellationModified(boolean modified) - { - setOptionFlag(modified, cancellationModified); - } - - public boolean isFontCancellationModified() - { - return getOptionFlag(cancellationModified); - } - - public void setEscapementTypeModified(boolean modified) - { - int value = modified? 0 : 1; - setInt(OFFSET_ESCAPEMENT_TYPE_MODIFIED, value); - } - public boolean isEscapementTypeModified() - { - int escapementModified = getInt(OFFSET_ESCAPEMENT_TYPE_MODIFIED); - return escapementModified == 0; - } - - public void setUnderlineTypeModified(boolean modified) - { - int value = modified? 0 : 1; - setInt(OFFSET_UNDERLINE_TYPE_MODIFIED, value); - } - - public boolean isUnderlineTypeModified() - { - int underlineModified = getInt(OFFSET_UNDERLINE_TYPE_MODIFIED); - return underlineModified == 0; - } - - public void setFontWieghtModified(boolean modified) - { - int value = modified? 0 : 1; - setInt(OFFSET_FONT_WEIGHT_MODIFIED, value); - } - - public boolean isFontWeightModified() - { - int fontStyleModified = getInt(OFFSET_FONT_WEIGHT_MODIFIED); - return fontStyleModified == 0; - } - - public String toString() - { - StringBuffer buffer = new StringBuffer(); - buffer.append(" [Font Formatting]\n"); - - buffer.append(" .font height = ").append(getFontHeight()).append(" twips\n"); - - if( isFontStyleModified() ) - { - buffer.append(" .font posture = ").append(isItalic()?"Italic":"Normal").append("\n"); - } - else - { - buffer.append(" .font posture = ]not modified]").append("\n"); - } - - if( isFontOutlineModified() ) - { - buffer.append(" .font outline = ").append(isOutlineOn()).append("\n"); - } - else - { - buffer.append(" .font outline is not modified\n"); - } - - if( isFontShadowModified() ) - { - buffer.append(" .font shadow = ").append(isShadowOn()).append("\n"); - } - else - { - buffer.append(" .font shadow is not modified\n"); - } - - if( isFontCancellationModified() ) - { - buffer.append(" .font strikeout = ").append(isStruckout()).append("\n"); - } - else - { - buffer.append(" .font strikeout is not modified\n"); - } - - if( isFontStyleModified() ) - { - buffer.append(" .font weight = "). - append(getFontWeight()). - append( - getFontWeight() == FONT_WEIGHT_NORMAL ? "(Normal)" - : getFontWeight() == FONT_WEIGHT_BOLD ? "(Bold)" : "0x"+Integer.toHexString(getFontWeight())). - append("\n"); - } - else - { - buffer.append(" .font weight = ]not modified]").append("\n"); - } - - if( isEscapementTypeModified() ) - { - buffer.append(" .escapement type = ").append(getEscapementType()).append("\n"); - } - else - { - buffer.append(" .escapement type is not modified\n"); - } - - if( isUnderlineTypeModified() ) - { - buffer.append(" .underline type = ").append(getUnderlineType()).append("\n"); - } - else - { - buffer.append(" .underline type is not modified\n"); - } - buffer.append(" .color index = ").append("0x"+Integer.toHexString(getFontColorIndex()).toUpperCase()).append("\n"); - - buffer.append(" [/Font Formatting]\n"); - return buffer.toString(); - } - - public Object clone() - { - byte[] rawData = _rawData.clone(); - return new FontFormatting(rawData); - } +public final class FontFormatting { + private byte[] _rawData; + + private static final int OFFSET_FONT_NAME = 0; + private static final int OFFSET_FONT_HEIGHT = 64; + private static final int OFFSET_FONT_OPTIONS = 68; + private static final int OFFSET_FONT_WEIGHT = 72; + private static final int OFFSET_ESCAPEMENT_TYPE = 74; + private static final int OFFSET_UNDERLINE_TYPE = 76; + private static final int OFFSET_FONT_COLOR_INDEX = 80; + private static final int OFFSET_OPTION_FLAGS = 88; + private static final int OFFSET_ESCAPEMENT_TYPE_MODIFIED = 92; + private static final int OFFSET_UNDERLINE_TYPE_MODIFIED = 96; + private static final int OFFSET_FONT_WEIGHT_MODIFIED = 100; + private static final int OFFSET_NOT_USED1 = 104; + private static final int OFFSET_NOT_USED2 = 108; + private static final int OFFSET_NOT_USED3 = 112; // for some reason Excel always writes 0x7FFFFFFF at this offset + private static final int OFFSET_FONT_FORMATING_END = 116; + private static final int RAW_DATA_SIZE = 118; + + + public final static int FONT_CELL_HEIGHT_PRESERVED = 0xFFFFFFFF; + + // FONT OPTIONS MASKS + private static final BitField posture = BitFieldFactory.getInstance(0x00000002); + private static final BitField outline = BitFieldFactory.getInstance(0x00000008); + private static final BitField shadow = BitFieldFactory.getInstance(0x00000010); + private static final BitField cancellation = BitFieldFactory.getInstance(0x00000080); + + // OPTION FLAGS MASKS + + private static final BitField styleModified = BitFieldFactory.getInstance(0x00000002); + private static final BitField outlineModified = BitFieldFactory.getInstance(0x00000008); + private static final BitField shadowModified = BitFieldFactory.getInstance(0x00000010); + private static final BitField cancellationModified = BitFieldFactory.getInstance(0x00000080); + + /** Escapement type - None */ + public static final short SS_NONE = 0; + /** Escapement type - Superscript */ + public static final short SS_SUPER = 1; + /** Escapement type - Subscript */ + public static final short SS_SUB = 2; + /** Underline type - None */ + public static final byte U_NONE = 0; + /** Underline type - Single */ + public static final byte U_SINGLE = 1; + /** Underline type - Double */ + public static final byte U_DOUBLE = 2; + /** Underline type - Single Accounting */ + public static final byte U_SINGLE_ACCOUNTING = 0x21; + /** Underline type - Double Accounting */ + public static final byte U_DOUBLE_ACCOUNTING = 0x22; + /** Normal boldness (not bold) */ + private static final short FONT_WEIGHT_NORMAL = 0x190; + + /** + * Bold boldness (bold) + */ + private static final short FONT_WEIGHT_BOLD = 0x2bc; + + private FontFormatting(byte[] rawData) { + _rawData = rawData; + } + + public FontFormatting() + { + this(new byte[RAW_DATA_SIZE]); + + setFontHeight(-1); + setItalic(false); + setFontWieghtModified(false); + setOutline(false); + setShadow(false); + setStrikeout(false); + setEscapementType((short)0); + setUnderlineType((byte)0); + setFontColorIndex((short)-1); + + setFontStyleModified(false); + setFontOutlineModified(false); + setFontShadowModified(false); + setFontCancellationModified(false); + + setEscapementTypeModified(false); + setUnderlineTypeModified(false); + + setShort(OFFSET_FONT_NAME, 0); + setInt(OFFSET_NOT_USED1, 0x00000001); + setInt(OFFSET_NOT_USED2, 0x00000000); + setInt(OFFSET_NOT_USED3, 0x7FFFFFFF);// for some reason Excel always writes 0x7FFFFFFF at this offset + setShort(OFFSET_FONT_FORMATING_END, 0x0001); + } + + /** Creates new FontFormatting */ + public FontFormatting(RecordInputStream in) + { + this(new byte[RAW_DATA_SIZE]); + for (int i = 0; i < _rawData.length; i++) + { + _rawData[i] = in.readByte(); + } + } + + private short getShort(int offset) { + return LittleEndian.getShort( _rawData, offset); + } + private void setShort(int offset, int value) { + LittleEndian.putShort( _rawData, offset, (short)value); + } + private int getInt(int offset) { + return LittleEndian.getInt( _rawData, offset); + } + private void setInt(int offset, int value) { + LittleEndian.putInt( _rawData, offset, value); + } + + public byte[] getRawRecord() + { + return _rawData; + } + + public int getDataLength() { + return RAW_DATA_SIZE; + } + + /** + * sets the height of the font in 1/20th point units + * + * + * @param height fontheight (in points/20); or -1 to preserve the cell font height + */ + + public void setFontHeight(int height) + { + setInt(OFFSET_FONT_HEIGHT, height); + } + + /** + * gets the height of the font in 1/20th point units + * + * @return fontheight (in points/20); or -1 if not modified + */ + public int getFontHeight() + { + return getInt(OFFSET_FONT_HEIGHT); + } + + private void setFontOption(boolean option, BitField field) + { + int options = getInt(OFFSET_FONT_OPTIONS); + options = field.setBoolean(options, option); + setInt(OFFSET_FONT_OPTIONS, options); + } + + private boolean getFontOption(BitField field) + { + int options = getInt(OFFSET_FONT_OPTIONS); + return field.isSet(options); + } + + /** + * set the font to be italics or not + * + * @param italic - whether the font is italics or not + * @see #setFontOption(boolean, org.apache.poi.util.BitField) + */ + + public void setItalic(boolean italic) + { + setFontOption(italic, posture); + } + + /** + * get whether the font is to be italics or not + * + * @return italics - whether the font is italics or not + * @see #getFontOption(org.apache.poi.util.BitField) + */ + + public boolean isItalic() + { + return getFontOption(posture); + } + + public void setOutline(boolean on) + { + setFontOption(on, outline); + } + + public boolean isOutlineOn() + { + return getFontOption(outline); + } + + public void setShadow(boolean on) + { + setFontOption(on, shadow); + } + + public boolean isShadowOn() + { + return getFontOption(shadow); + } + + /** + * set the font to be stricken out or not + * + * @param strike - whether the font is stricken out or not + */ + public void setStrikeout(boolean strike) + { + setFontOption(strike, cancellation); + } + + /** + * get whether the font is to be stricken out or not + * + * @return strike - whether the font is stricken out or not + * @see #getFontOption(org.apache.poi.util.BitField) + */ + public boolean isStruckout() + { + return getFontOption(cancellation); + } + + /** + * set the font weight (100-1000dec or 0x64-0x3e8). Default is + * 0x190 for normal and 0x2bc for bold + * + * @param bw - a number between 100-1000 for the fonts "boldness" + */ + + private void setFontWeight(short pbw) + { + short bw = pbw; + if( bw<100) { bw=100; } + if( bw>1000){ bw=1000; } + setShort(OFFSET_FONT_WEIGHT, bw); + } + + /** + * set the font weight to bold (weight=700) or to normal(weight=400) boldness. + * + * @param bold - set font weight to bold if true; to normal otherwise + */ + public void setBold(boolean bold) + { + setFontWeight(bold?FONT_WEIGHT_BOLD:FONT_WEIGHT_NORMAL); + } + + /** + * get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is + * 0x190 for normal and 0x2bc for bold + * + * @return bw - a number between 100-1000 for the fonts "boldness" + */ + + public short getFontWeight() + { + return getShort(OFFSET_FONT_WEIGHT); + } + + /** + * get whether the font weight is set to bold or not + * + * @return bold - whether the font is bold or not + */ + + public boolean isBold() + { + return getFontWeight()==FONT_WEIGHT_BOLD; + } + + /** + * get the type of super or subscript for the font + * + * @return super or subscript option + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_NONE + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUPER + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUB + */ + public short getEscapementType() + { + return getShort(OFFSET_ESCAPEMENT_TYPE); + } + + /** + * set the escapement type for the font + * + * @param escapementType super or subscript option + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_NONE + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUPER + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#SS_SUB + */ + public void setEscapementType( short escapementType) + { + setShort(OFFSET_ESCAPEMENT_TYPE, escapementType); + } + + /** + * get the type of underlining for the font + * + * @return font underlining type + * + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE_ACCOUNTING + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE_ACCOUNTING + */ + public short getUnderlineType() + { + return getShort(OFFSET_UNDERLINE_TYPE); + } + + /** + * set the type of underlining type for the font + * + * @param underlineType underline option + * + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_NONE + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_SINGLE_ACCOUNTING + * @see org.apache.poi.hssf.usermodel.HSSFFontFormatting#U_DOUBLE_ACCOUNTING + */ + public void setUnderlineType( short underlineType) + { + setShort(OFFSET_UNDERLINE_TYPE, underlineType); + } + + + public short getFontColorIndex() + { + return (short)getInt(OFFSET_FONT_COLOR_INDEX); + } + + public void setFontColorIndex(short fci ) + { + setInt(OFFSET_FONT_COLOR_INDEX,fci); + } + + private boolean getOptionFlag(BitField field) { + int optionFlags = getInt(OFFSET_OPTION_FLAGS); + int value = field.getValue(optionFlags); + return value==0? true : false ; + } + + private void setOptionFlag(boolean modified, BitField field) + { + int value = modified? 0 : 1; + int optionFlags = getInt(OFFSET_OPTION_FLAGS); + optionFlags = field.setValue(optionFlags, value); + setInt(OFFSET_OPTION_FLAGS, optionFlags); + } + + + public boolean isFontStyleModified() + { + return getOptionFlag(styleModified); + } + + + public void setFontStyleModified(boolean modified) + { + setOptionFlag(modified, styleModified); + } + + public boolean isFontOutlineModified() + { + return getOptionFlag(outlineModified); + } + + public void setFontOutlineModified(boolean modified) + { + setOptionFlag(modified, outlineModified); + } + + public boolean isFontShadowModified() + { + return getOptionFlag(shadowModified); + } + + public void setFontShadowModified(boolean modified) + { + setOptionFlag(modified, shadowModified); + } + public void setFontCancellationModified(boolean modified) + { + setOptionFlag(modified, cancellationModified); + } + + public boolean isFontCancellationModified() + { + return getOptionFlag(cancellationModified); + } + + public void setEscapementTypeModified(boolean modified) + { + int value = modified? 0 : 1; + setInt(OFFSET_ESCAPEMENT_TYPE_MODIFIED, value); + } + public boolean isEscapementTypeModified() + { + int escapementModified = getInt(OFFSET_ESCAPEMENT_TYPE_MODIFIED); + return escapementModified == 0; + } + + public void setUnderlineTypeModified(boolean modified) + { + int value = modified? 0 : 1; + setInt(OFFSET_UNDERLINE_TYPE_MODIFIED, value); + } + + public boolean isUnderlineTypeModified() + { + int underlineModified = getInt(OFFSET_UNDERLINE_TYPE_MODIFIED); + return underlineModified == 0; + } + + public void setFontWieghtModified(boolean modified) + { + int value = modified? 0 : 1; + setInt(OFFSET_FONT_WEIGHT_MODIFIED, value); + } + + public boolean isFontWeightModified() + { + int fontStyleModified = getInt(OFFSET_FONT_WEIGHT_MODIFIED); + return fontStyleModified == 0; + } + + public String toString() + { + StringBuffer buffer = new StringBuffer(); + buffer.append(" [Font Formatting]\n"); + + buffer.append(" .font height = ").append(getFontHeight()).append(" twips\n"); + + if( isFontStyleModified() ) + { + buffer.append(" .font posture = ").append(isItalic()?"Italic":"Normal").append("\n"); + } + else + { + buffer.append(" .font posture = ]not modified]").append("\n"); + } + + if( isFontOutlineModified() ) + { + buffer.append(" .font outline = ").append(isOutlineOn()).append("\n"); + } + else + { + buffer.append(" .font outline is not modified\n"); + } + + if( isFontShadowModified() ) + { + buffer.append(" .font shadow = ").append(isShadowOn()).append("\n"); + } + else + { + buffer.append(" .font shadow is not modified\n"); + } + + if( isFontCancellationModified() ) + { + buffer.append(" .font strikeout = ").append(isStruckout()).append("\n"); + } + else + { + buffer.append(" .font strikeout is not modified\n"); + } + + if( isFontStyleModified() ) + { + buffer.append(" .font weight = "). + append(getFontWeight()). + append( + getFontWeight() == FONT_WEIGHT_NORMAL ? "(Normal)" + : getFontWeight() == FONT_WEIGHT_BOLD ? "(Bold)" + : "0x"+Integer.toHexString(getFontWeight())). + append("\n"); + } + else + { + buffer.append(" .font weight = ]not modified]").append("\n"); + } + + if( isEscapementTypeModified() ) + { + buffer.append(" .escapement type = ").append(getEscapementType()).append("\n"); + } + else + { + buffer.append(" .escapement type is not modified\n"); + } + + if( isUnderlineTypeModified() ) + { + buffer.append(" .underline type = ").append(getUnderlineType()).append("\n"); + } + else + { + buffer.append(" .underline type is not modified\n"); + } + buffer.append(" .color index = ").append("0x"+Integer.toHexString(getFontColorIndex()).toUpperCase()).append("\n"); + + buffer.append(" [/Font Formatting]\n"); + return buffer.toString(); + } + + public Object clone() + { + byte[] rawData = _rawData.clone(); + return new FontFormatting(rawData); + } } diff --git a/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java new file mode 100644 index 000000000..f405c031e --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/cf/IconMultiStateFormatting.java @@ -0,0 +1,139 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record.cf; + +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; +import org.apache.poi.util.BitField; +import org.apache.poi.util.BitFieldFactory; +import org.apache.poi.util.LittleEndianInput; +import org.apache.poi.util.LittleEndianOutput; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * Icon / Multi-State Conditional Formatting Rule Record. + */ +public final class IconMultiStateFormatting implements Cloneable { + private static POILogger log = POILogFactory.getLogger(IconMultiStateFormatting.class); + + private IconSet iconSet; + private byte options; + private Threshold[] thresholds; + + private static BitField iconOnly = BitFieldFactory.getInstance(0x01); + private static BitField reversed = BitFieldFactory.getInstance(0x04); + + public IconMultiStateFormatting() { + iconSet = IconSet.GYR_3_TRAFFIC_LIGHTS; + options = 0; + thresholds = new Threshold[iconSet.num]; + } + public IconMultiStateFormatting(LittleEndianInput in) { + in.readShort(); // Ignored + in.readByte(); // Reserved + int num = in.readByte(); + int set = in.readByte(); + iconSet = IconSet.byId(set); + if (iconSet.num != num) { + log.log(POILogger.WARN, "Inconsistent Icon Set defintion, found " + iconSet + " but defined as " + num + " entries"); + } + options = in.readByte(); + + thresholds = new Threshold[iconSet.num]; + for (int i=0; i 0) { + formula = Formula.read(formulaLen, in); + } else { + formula = Formula.create(null); + } + // Value is only there for non-formula, non min/max thresholds + if (formulaLen == 0 && type != RangeType.MIN.id && + type != RangeType.MAX.id) { + value = in.readDouble(); + } + equals = in.readByte(); + // Reserved, 4 bytes, all 0 + in.readInt(); + } + + public byte getType() { + return type; + } + public void setType(byte type) { + this.type = type; + } + public void setType(int type) { + this.type = (byte)type; + } + + protected Formula getFormula() { + return formula; + } + public Ptg[] getParsedExpression() { + return formula.getTokens(); + } + public void setParsedExpression(Ptg[] ptgs) { + formula = Formula.create(ptgs); + } + + public Double getValue() { + return value; + } + public void setValue(Double value) { + this.value = value; + } + + public byte getEquals() { + return equals; + } + public void setEquals(byte equals) { + this.equals = equals; + } + + public int getDataLength() { + int len = 1 + formula.getEncodedSize(); + if (value != null) { + len += 8; + } + len += 5; + return len; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(" [CF Threshold]\n"); + buffer.append(" .type = ").append(Integer.toHexString(type)).append("\n"); + buffer.append(" .formula = ").append(Arrays.toString(formula.getTokens())).append("\n"); + buffer.append(" .value = ").append(value).append("\n"); + buffer.append(" [/CF Threshold]\n"); + return buffer.toString(); + } + + public Object clone() { + Threshold rec = new Threshold(); + rec.type = type; + rec.formula = formula; + rec.value = value; + rec.equals = equals; + return rec; + } + + public void serialize(LittleEndianOutput out) { + out.writeByte(type); + if (formula.getTokens().length == 0) { + out.writeShort(0); + } else { + formula.serialize(out); + } + if (value != null) { + out.writeDouble(value); + } + out.writeByte(equals); + out.writeInt(0); // Reserved + } +} diff --git a/src/java/org/apache/poi/hssf/record/common/FtrHeader.java b/src/java/org/apache/poi/hssf/record/common/FtrHeader.java index dc2d4e26e..dba24f084 100644 --- a/src/java/org/apache/poi/hssf/record/common/FtrHeader.java +++ b/src/java/org/apache/poi/hssf/record/common/FtrHeader.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.record.common; import org.apache.poi.hssf.record.RecordInputStream; +import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.LittleEndianOutput; /** @@ -28,62 +29,69 @@ import org.apache.poi.util.LittleEndianOutput; * beyond those of a traditional record. */ public final class FtrHeader { - /** This MUST match the type on the containing record */ - private short recordType; - /** This is a FrtFlags */ - private short grbitFrt; - /** MUST be 8 bytes and all zero */ - private byte[] reserved; + /** This MUST match the type on the containing record */ + private short recordType; + /** This is a FrtFlags */ + private short grbitFrt; + /** The range of cells the parent record applies to, or 0 if N/A */ + private CellRangeAddress associatedRange; - public FtrHeader() { - reserved = new byte[8]; - } + public FtrHeader() { + associatedRange = new CellRangeAddress(0, 0, 0, 0); + } - public FtrHeader(RecordInputStream in) { - recordType = in.readShort(); - grbitFrt = in.readShort(); - - reserved = new byte[8]; - in.read(reserved, 0, 8); - } + public FtrHeader(RecordInputStream in) { + recordType = in.readShort(); + grbitFrt = in.readShort(); - public String toString() { - StringBuffer buffer = new StringBuffer(); - buffer.append(" [FUTURE HEADER]\n"); - buffer.append(" Type " + recordType); - buffer.append(" Flags " + grbitFrt); - buffer.append(" [/FUTURE HEADER]\n"); - return buffer.toString(); - } + associatedRange = new CellRangeAddress(in); + } - public void serialize(LittleEndianOutput out) { - out.writeShort(recordType); - out.writeShort(grbitFrt); - out.write(reserved); - } + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(" [FUTURE HEADER]\n"); + buffer.append(" Type " + recordType); + buffer.append(" Flags " + grbitFrt); + buffer.append(" [/FUTURE HEADER]\n"); + return buffer.toString(); + } - public static int getDataSize() { - return 12; - } + public void serialize(LittleEndianOutput out) { + out.writeShort(recordType); + out.writeShort(grbitFrt); + associatedRange.serialize(out); + } - public short getRecordType() { - return recordType; - } - public void setRecordType(short recordType) { - this.recordType = recordType; - } + public static int getDataSize() { + return 12; + } - public short getGrbitFrt() { - return grbitFrt; - } - public void setGrbitFrt(short grbitFrt) { - this.grbitFrt = grbitFrt; - } + public short getRecordType() { + return recordType; + } + public void setRecordType(short recordType) { + this.recordType = recordType; + } - public byte[] getReserved() { - return reserved; - } - public void setReserved(byte[] reserved) { - this.reserved = reserved; - } + public short getGrbitFrt() { + return grbitFrt; + } + public void setGrbitFrt(short grbitFrt) { + this.grbitFrt = grbitFrt; + } + + public CellRangeAddress getAssociatedRange() { + return associatedRange; + } + public void setAssociatedRange(CellRangeAddress associatedRange) { + this.associatedRange = associatedRange; + } + + public Object clone() { + FtrHeader result = new FtrHeader(); + result.recordType = recordType; + result.grbitFrt = grbitFrt; + result.associatedRange = associatedRange.copy(); + return result; + } } \ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/common/FutureRecord.java b/src/java/org/apache/poi/hssf/record/common/FutureRecord.java new file mode 100644 index 000000000..65a26cca7 --- /dev/null +++ b/src/java/org/apache/poi/hssf/record/common/FutureRecord.java @@ -0,0 +1,30 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.record.common; + +import org.apache.poi.ss.util.CellRangeAddress; + +/** + * Title: Future Record, a newer (largely Excel 2007+) record + * which contains a Future Record Header ({@link FtrHeader}) + */ +public interface FutureRecord { + public short getFutureRecordType(); + public FtrHeader getFutureHeader(); + public CellRangeAddress getAssociatedRange(); +} \ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java b/src/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java index f52a15d81..564174b60 100644 --- a/src/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java +++ b/src/java/org/apache/poi/hssf/record/crypto/Biff8DecryptingStream.java @@ -95,7 +95,7 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia public int readUByte() { - return _cipher.xorByte(_le.readUByte()); + return readByte() & 0xFF; } public byte readByte() { return (byte) _cipher.xorByte(_le.readUByte()); @@ -103,7 +103,7 @@ public final class Biff8DecryptingStream implements BiffHeaderInput, LittleEndia public int readUShort() { - return _cipher.xorShort(_le.readUShort()); + return readShort() & 0xFFFF; } public short readShort() { return (short) _cipher.xorShort(_le.readUShort()); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java index 0e2cb9d20..c5c996456 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFBorderFormatting.java @@ -17,196 +17,246 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.hssf.record.CFRuleRecord; +import org.apache.poi.hssf.record.CFRuleBase; import org.apache.poi.hssf.record.cf.BorderFormatting; +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.Color; /** * High level representation for Border Formatting component * of Conditional Formatting settings */ -public final class HSSFBorderFormatting implements org.apache.poi.ss.usermodel.BorderFormatting -{ - private final CFRuleRecord cfRuleRecord; - private final BorderFormatting borderFormatting; - - protected HSSFBorderFormatting(CFRuleRecord cfRuleRecord) - { - this.cfRuleRecord = cfRuleRecord; - this.borderFormatting = cfRuleRecord.getBorderFormatting(); - } +public final class HSSFBorderFormatting implements org.apache.poi.ss.usermodel.BorderFormatting { + private final HSSFWorkbook workbook; + private final CFRuleBase cfRuleRecord; + private final BorderFormatting borderFormatting; - protected BorderFormatting getBorderFormattingBlock() - { - return borderFormatting; - } + protected HSSFBorderFormatting(CFRuleBase cfRuleRecord, HSSFWorkbook workbook) { + this.workbook = workbook; + this.cfRuleRecord = cfRuleRecord; + this.borderFormatting = cfRuleRecord.getBorderFormatting(); + } - public short getBorderBottom() - { - return (short)borderFormatting.getBorderBottom(); - } + protected BorderFormatting getBorderFormattingBlock() { + return borderFormatting; + } - public short getBorderDiagonal() - { - return (short)borderFormatting.getBorderDiagonal(); - } + public short getBorderBottom() { + return (short)borderFormatting.getBorderBottom(); + } - public short getBorderLeft() - { - return (short)borderFormatting.getBorderLeft(); - } + public short getBorderDiagonal() { + return (short)borderFormatting.getBorderDiagonal(); + } - public short getBorderRight() - { - return (short)borderFormatting.getBorderRight(); - } + public short getBorderLeft() { + return (short)borderFormatting.getBorderLeft(); + } - public short getBorderTop() - { - return (short)borderFormatting.getBorderTop(); - } + public short getBorderRight() { + return (short)borderFormatting.getBorderRight(); + } - public short getBottomBorderColor() - { - return (short)borderFormatting.getBottomBorderColor(); - } + public short getBorderTop() { + return (short)borderFormatting.getBorderTop(); + } - public short getDiagonalBorderColor() - { - return (short)borderFormatting.getDiagonalBorderColor(); - } + public short getBottomBorderColor() { + return (short)borderFormatting.getBottomBorderColor(); + } + public HSSFColor getBottomBorderColorColor() { + return workbook.getCustomPalette().getColor( + borderFormatting.getBottomBorderColor() + ); + } - public short getLeftBorderColor() - { - return (short)borderFormatting.getLeftBorderColor(); - } + public short getDiagonalBorderColor() { + return (short)borderFormatting.getDiagonalBorderColor(); + } + public HSSFColor getDiagonalBorderColorColor() { + return workbook.getCustomPalette().getColor( + borderFormatting.getDiagonalBorderColor() + ); + } - public short getRightBorderColor() - { - return (short)borderFormatting.getRightBorderColor(); - } + public short getLeftBorderColor() { + return (short)borderFormatting.getLeftBorderColor(); + } + public HSSFColor getLeftBorderColorColor() { + return workbook.getCustomPalette().getColor( + borderFormatting.getLeftBorderColor() + ); + } - public short getTopBorderColor() - { - return (short)borderFormatting.getTopBorderColor(); - } + public short getRightBorderColor() { + return (short)borderFormatting.getRightBorderColor(); + } + public HSSFColor getRightBorderColorColor() { + return workbook.getCustomPalette().getColor( + borderFormatting.getRightBorderColor() + ); + } - public boolean isBackwardDiagonalOn() - { - return borderFormatting.isBackwardDiagonalOn(); - } + public short getTopBorderColor() { + return (short)borderFormatting.getTopBorderColor(); + } + public HSSFColor getTopBorderColorColor() { + return workbook.getCustomPalette().getColor( + borderFormatting.getTopBorderColor() + ); + } - public boolean isForwardDiagonalOn() - { - return borderFormatting.isForwardDiagonalOn(); - } + public boolean isBackwardDiagonalOn() { + return borderFormatting.isBackwardDiagonalOn(); + } + public boolean isForwardDiagonalOn() { + return borderFormatting.isForwardDiagonalOn(); + } - public void setBackwardDiagonalOn(boolean on) - { - borderFormatting.setBackwardDiagonalOn(on); - if( on ) - { - cfRuleRecord.setTopLeftBottomRightBorderModified(on); - } - } + public void setBackwardDiagonalOn(boolean on) { + borderFormatting.setBackwardDiagonalOn(on); + if (on) { + cfRuleRecord.setTopLeftBottomRightBorderModified(on); + } + } + public void setForwardDiagonalOn(boolean on) { + borderFormatting.setForwardDiagonalOn(on); + if (on) { + cfRuleRecord.setBottomLeftTopRightBorderModified(on); + } + } - public void setBorderBottom(short border) - { - borderFormatting.setBorderBottom(border); - if( border != 0) - { - cfRuleRecord.setBottomBorderModified(true); - } - } + public void setBorderBottom(short border) { + borderFormatting.setBorderBottom(border); + if (border != 0) { + cfRuleRecord.setBottomBorderModified(true); + } else { + cfRuleRecord.setBottomBorderModified(false); + } + } - public void setBorderDiagonal(short border) - { - borderFormatting.setBorderDiagonal(border); - if( border != 0) - { - cfRuleRecord.setBottomLeftTopRightBorderModified(true); - cfRuleRecord.setTopLeftBottomRightBorderModified(true); - } - } + public void setBorderDiagonal(short border) { + borderFormatting.setBorderDiagonal(border); + if (border != 0) { + cfRuleRecord.setBottomLeftTopRightBorderModified(true); + cfRuleRecord.setTopLeftBottomRightBorderModified(true); + } else { + cfRuleRecord.setBottomLeftTopRightBorderModified(false); + cfRuleRecord.setTopLeftBottomRightBorderModified(false); + } + } - public void setBorderLeft(short border) - { - borderFormatting.setBorderLeft(border); - if( border != 0) - { - cfRuleRecord.setLeftBorderModified(true); - } - } + public void setBorderLeft(short border) { + borderFormatting.setBorderLeft(border); + if (border != 0) { + cfRuleRecord.setLeftBorderModified(true); + } else { + cfRuleRecord.setLeftBorderModified(false); + } + } - public void setBorderRight(short border) - { - borderFormatting.setBorderRight(border); - if( border != 0) - { - cfRuleRecord.setRightBorderModified(true); - } - } + public void setBorderRight(short border) { + borderFormatting.setBorderRight(border); + if (border != 0) { + cfRuleRecord.setRightBorderModified(true); + } else { + cfRuleRecord.setRightBorderModified(false); + } + } - public void setBorderTop(short border) - { - borderFormatting.setBorderTop(border); - if( border != 0) - { - cfRuleRecord.setTopBorderModified(true); - } - } + public void setBorderTop(short border) { + borderFormatting.setBorderTop(border); + if (border != 0) { + cfRuleRecord.setTopBorderModified(true); + } else { + cfRuleRecord.setTopBorderModified(false); + } + } - public void setBottomBorderColor(short color) - { - borderFormatting.setBottomBorderColor(color); - if( color != 0) - { - cfRuleRecord.setBottomBorderModified(true); - } - } + public void setBottomBorderColor(short color) { + borderFormatting.setBottomBorderColor(color); + if (color != 0) { + cfRuleRecord.setBottomBorderModified(true); + } else { + cfRuleRecord.setBottomBorderModified(false); + } + } + public void setBottomBorderColor(Color color) { + HSSFColor hcolor = HSSFColor.toHSSFColor(color); + if (hcolor == null) { + setBottomBorderColor((short)0); + } else { + setBottomBorderColor(hcolor.getIndex()); + } + } - public void setDiagonalBorderColor(short color) - { - borderFormatting.setDiagonalBorderColor(color); - if( color != 0) - { - cfRuleRecord.setBottomLeftTopRightBorderModified(true); - cfRuleRecord.setTopLeftBottomRightBorderModified(true); - } - } + public void setDiagonalBorderColor(short color) { + borderFormatting.setDiagonalBorderColor(color); + if (color != 0) { + cfRuleRecord.setBottomLeftTopRightBorderModified(true); + cfRuleRecord.setTopLeftBottomRightBorderModified(true); + } else { + cfRuleRecord.setBottomLeftTopRightBorderModified(false); + cfRuleRecord.setTopLeftBottomRightBorderModified(false); + } + } + public void setDiagonalBorderColor(Color color) { + HSSFColor hcolor = HSSFColor.toHSSFColor(color); + if (hcolor == null) { + setDiagonalBorderColor((short)0); + } else { + setDiagonalBorderColor(hcolor.getIndex()); + } + } - public void setForwardDiagonalOn(boolean on) - { - borderFormatting.setForwardDiagonalOn(on); - if( on ) - { - cfRuleRecord.setBottomLeftTopRightBorderModified(on); - } - } + public void setLeftBorderColor(short color) { + borderFormatting.setLeftBorderColor(color); + if (color != 0) { + cfRuleRecord.setLeftBorderModified(true); + } else { + cfRuleRecord.setLeftBorderModified(false); + } + } + public void setLeftBorderColor(Color color) { + HSSFColor hcolor = HSSFColor.toHSSFColor(color); + if (hcolor == null) { + setLeftBorderColor((short)0); + } else { + setLeftBorderColor(hcolor.getIndex()); + } + } - public void setLeftBorderColor(short color) - { - borderFormatting.setLeftBorderColor(color); - if( color != 0) - { - cfRuleRecord.setLeftBorderModified(true); - } - } + public void setRightBorderColor(short color) { + borderFormatting.setRightBorderColor(color); + if (color != 0) { + cfRuleRecord.setRightBorderModified(true); + } else { + cfRuleRecord.setRightBorderModified(false); + } + } + public void setRightBorderColor(Color color) { + HSSFColor hcolor = HSSFColor.toHSSFColor(color); + if (hcolor == null) { + setRightBorderColor((short)0); + } else { + setRightBorderColor(hcolor.getIndex()); + } + } - public void setRightBorderColor(short color) - { - borderFormatting.setRightBorderColor(color); - if( color != 0) - { - cfRuleRecord.setRightBorderModified(true); - } - } - - public void setTopBorderColor(short color) - { - borderFormatting.setTopBorderColor(color); - if( color != 0) - { - cfRuleRecord.setTopBorderModified(true); - } - } + public void setTopBorderColor(short color) { + borderFormatting.setTopBorderColor(color); + if (color != 0) { + cfRuleRecord.setTopBorderModified(true); + } else { + cfRuleRecord.setTopBorderModified(false); + } + } + public void setTopBorderColor(Color color) { + HSSFColor hcolor = HSSFColor.toHSSFColor(color); + if (hcolor == null) { + setTopBorderColor((short)0); + } else { + setTopBorderColor(hcolor.getIndex()); + } + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index e5de299a0..b1e8b7a00 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -538,18 +538,17 @@ public class HSSFCell implements Cell { public void setCellValue(RichTextString value) { - HSSFRichTextString hvalue = (HSSFRichTextString) value; int row=_record.getRow(); short col=_record.getColumn(); short styleIndex=_record.getXFIndex(); - if (hvalue == null) + if (value == null) { notifyFormulaChanging(); setCellType(CELL_TYPE_BLANK, false, row, col, styleIndex); return; } - if(hvalue.length() > SpreadsheetVersion.EXCEL97.getMaxTextLength()){ + if(value.length() > SpreadsheetVersion.EXCEL97.getMaxTextLength()){ throw new IllegalArgumentException("The maximum length of cell contents (text) is 32,767 characters"); } @@ -557,7 +556,7 @@ public class HSSFCell implements Cell { // Set the 'pre-evaluated result' for the formula // note - formulas do not preserve text formatting. FormulaRecordAggregate fr = (FormulaRecordAggregate) _record; - fr.setCachedStringResult(hvalue.getString()); + fr.setCachedStringResult(value.getString()); // Update our local cache to the un-formatted version _stringValue = new HSSFRichTextString(value.getString()); @@ -573,6 +572,7 @@ public class HSSFCell implements Cell { } int index = 0; + HSSFRichTextString hvalue = (HSSFRichTextString) value; UnicodeString str = hvalue.getUnicodeString(); index = _book.getWorkbook().addSSTString(str); (( LabelSSTRecord ) _record).setSSTIndex(index); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java index 81de3a41d..4e71ac2b8 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFComment.java @@ -129,10 +129,13 @@ public class HSSFComment extends HSSFTextbox implements Comment { @Override void setShapeId(int shapeId) { + if(shapeId > 65535) { + throw new IllegalArgumentException("Cannot add more than " + 65535 + " shapes"); + } super.setShapeId(shapeId); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) getObjRecord().getSubRecords().get(0); - cod.setObjectId((short) (shapeId % 1024)); - _note.setShapeId(shapeId % 1024); + cod.setObjectId(shapeId); + _note.setShapeId(shapeId); } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java index b0f1474bf..e5792770c 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormatting.java @@ -16,7 +16,7 @@ ==================================================================== */ package org.apache.poi.hssf.usermodel; -import org.apache.poi.hssf.record.CFRuleRecord; +import org.apache.poi.hssf.record.CFRuleBase; import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate; import org.apache.poi.ss.usermodel.ConditionalFormatting; import org.apache.poi.ss.usermodel.ConditionalFormattingRule; @@ -73,91 +73,84 @@ import org.apache.poi.ss.util.CellRangeAddress; * sheet.addConditionalFormatting(regions, rule); * */ -public final class HSSFConditionalFormatting implements ConditionalFormatting -{ - private final HSSFWorkbook _workbook; - private final CFRecordsAggregate cfAggregate; +public final class HSSFConditionalFormatting implements ConditionalFormatting { + private final HSSFSheet sheet; + private final CFRecordsAggregate cfAggregate; - HSSFConditionalFormatting(HSSFWorkbook workbook, CFRecordsAggregate cfAggregate) - { - if(workbook == null) { - throw new IllegalArgumentException("workbook must not be null"); - } - if(cfAggregate == null) { - throw new IllegalArgumentException("cfAggregate must not be null"); - } - _workbook = workbook; - this.cfAggregate = cfAggregate; - } - CFRecordsAggregate getCFRecordsAggregate() { - return cfAggregate; - } + HSSFConditionalFormatting(HSSFSheet sheet, CFRecordsAggregate cfAggregate) { + if(sheet == null) { + throw new IllegalArgumentException("sheet must not be null"); + } + if(cfAggregate == null) { + throw new IllegalArgumentException("cfAggregate must not be null"); + } + this.sheet = sheet; + this.cfAggregate = cfAggregate; + } + CFRecordsAggregate getCFRecordsAggregate() { + return cfAggregate; + } - /** - * @deprecated (Aug-2008) use {@link HSSFConditionalFormatting#getFormattingRanges()} - */ - public org.apache.poi.ss.util.Region[] getFormattingRegions() - { - CellRangeAddress[] cellRanges = getFormattingRanges(); - return org.apache.poi.ss.util.Region.convertCellRangesToRegions(cellRanges); - } - /** - * @return array of CellRangeAddresss. never null - */ - public CellRangeAddress[] getFormattingRanges() { - return cfAggregate.getHeader().getCellRanges(); - } + /** + * @deprecated (Aug-2008) use {@link HSSFConditionalFormatting#getFormattingRanges()} + */ + public org.apache.poi.ss.util.Region[] getFormattingRegions() { + CellRangeAddress[] cellRanges = getFormattingRanges(); + return org.apache.poi.ss.util.Region.convertCellRangesToRegions(cellRanges); + } + /** + * @return array of CellRangeAddresss. never null + */ + public CellRangeAddress[] getFormattingRanges() { + return cfAggregate.getHeader().getCellRanges(); + } - /** - * Replaces an existing Conditional Formatting rule at position idx. - * Excel allows to create up to 3 Conditional Formatting rules. - * This method can be useful to modify existing Conditional Formatting rules. - * - * @param idx position of the rule. Should be between 0 and 2. - * @param cfRule - Conditional Formatting rule - */ - public void setRule(int idx, HSSFConditionalFormattingRule cfRule) - { - cfAggregate.setRule(idx, cfRule.getCfRuleRecord()); - } + /** + * Replaces an existing Conditional Formatting rule at position idx. + * Older versions of Excel only allow up to 3 Conditional Formatting rules, + * and will ignore rules beyond that, while newer versions are fine. + * This method can be useful to modify existing Conditional Formatting rules. + * + * @param idx position of the rule. Should be between 0 and 2 for older Excel versions + * @param cfRule - Conditional Formatting rule + */ + public void setRule(int idx, HSSFConditionalFormattingRule cfRule) { + cfAggregate.setRule(idx, cfRule.getCfRuleRecord()); + } public void setRule(int idx, ConditionalFormattingRule cfRule){ setRule(idx, (HSSFConditionalFormattingRule)cfRule); } - /** - * add a Conditional Formatting rule. - * Excel allows to create up to 3 Conditional Formatting rules. - * @param cfRule - Conditional Formatting rule - */ - public void addRule(HSSFConditionalFormattingRule cfRule) - { - cfAggregate.addRule(cfRule.getCfRuleRecord()); - } + /** + * add a Conditional Formatting rule. + * Excel allows to create up to 3 Conditional Formatting rules. + * @param cfRule - Conditional Formatting rule + */ + public void addRule(HSSFConditionalFormattingRule cfRule) { + cfAggregate.addRule(cfRule.getCfRuleRecord()); + } public void addRule(ConditionalFormattingRule cfRule){ addRule((HSSFConditionalFormattingRule)cfRule); } - /** - * @return the Conditional Formatting rule at position idx. - */ - public HSSFConditionalFormattingRule getRule(int idx) - { - CFRuleRecord ruleRecord = cfAggregate.getRule(idx); - return new HSSFConditionalFormattingRule(_workbook, ruleRecord); - } + /** + * @return the Conditional Formatting rule at position idx. + */ + public HSSFConditionalFormattingRule getRule(int idx) { + CFRuleBase ruleRecord = cfAggregate.getRule(idx); + return new HSSFConditionalFormattingRule(sheet, ruleRecord); + } - /** - * @return number of Conditional Formatting rules. - */ - public int getNumberOfRules() - { - return cfAggregate.getNumberOfRules(); - } + /** + * @return number of Conditional Formatting rules. + */ + public int getNumberOfRules() { + return cfAggregate.getNumberOfRules(); + } - public String toString() - { - return cfAggregate.toString(); - } + public String toString() { + return cfAggregate.toString(); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java index 6d881132f..a999488d3 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingRule.java @@ -18,12 +18,16 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.hssf.model.HSSFFormulaParser; +import org.apache.poi.hssf.record.CFRule12Record; +import org.apache.poi.hssf.record.CFRuleBase; +import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator; import org.apache.poi.hssf.record.CFRuleRecord; -import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator; import org.apache.poi.hssf.record.cf.BorderFormatting; import org.apache.poi.hssf.record.cf.FontFormatting; +import org.apache.poi.hssf.record.cf.IconMultiStateFormatting; import org.apache.poi.hssf.record.cf.PatternFormatting; import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.ss.usermodel.ConditionType; import org.apache.poi.ss.usermodel.ConditionalFormattingRule; /** @@ -32,178 +36,224 @@ import org.apache.poi.ss.usermodel.ConditionalFormattingRule; * It allows to specify formula based conditions for the Conditional Formatting * and the formatting settings such as font, border and pattern. */ -public final class HSSFConditionalFormattingRule implements ConditionalFormattingRule -{ - private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS; +public final class HSSFConditionalFormattingRule implements ConditionalFormattingRule { + private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS; - private final CFRuleRecord cfRuleRecord; - private final HSSFWorkbook workbook; + private final CFRuleBase cfRuleRecord; + private final HSSFWorkbook workbook; + private final HSSFSheet sheet; - HSSFConditionalFormattingRule(HSSFWorkbook pWorkbook, CFRuleRecord pRuleRecord) { - if (pWorkbook == null) { - throw new IllegalArgumentException("pWorkbook must not be null"); - } - if (pRuleRecord == null) { - throw new IllegalArgumentException("pRuleRecord must not be null"); - } - workbook = pWorkbook; - cfRuleRecord = pRuleRecord; - } + HSSFConditionalFormattingRule(HSSFSheet pSheet, CFRuleBase pRuleRecord) { + if (pSheet == null) { + throw new IllegalArgumentException("pSheet must not be null"); + } + if (pRuleRecord == null) { + throw new IllegalArgumentException("pRuleRecord must not be null"); + } + sheet = pSheet; + workbook = pSheet.getWorkbook(); + cfRuleRecord = pRuleRecord; + } - CFRuleRecord getCfRuleRecord() - { - return cfRuleRecord; - } + CFRuleBase getCfRuleRecord() + { + return cfRuleRecord; + } - private HSSFFontFormatting getFontFormatting(boolean create) - { - FontFormatting fontFormatting = cfRuleRecord.getFontFormatting(); - if ( fontFormatting != null) - { - cfRuleRecord.setFontFormatting(fontFormatting); - return new HSSFFontFormatting(cfRuleRecord); - } - else if( create ) - { - fontFormatting = new FontFormatting(); - cfRuleRecord.setFontFormatting(fontFormatting); - return new HSSFFontFormatting(cfRuleRecord); - } - else - { - return null; - } - } + private HSSFFontFormatting getFontFormatting(boolean create) + { + FontFormatting fontFormatting = cfRuleRecord.getFontFormatting(); + if ( fontFormatting != null) + { + cfRuleRecord.setFontFormatting(fontFormatting); + return new HSSFFontFormatting(cfRuleRecord, workbook); + } + else if( create ) + { + fontFormatting = new FontFormatting(); + cfRuleRecord.setFontFormatting(fontFormatting); + return new HSSFFontFormatting(cfRuleRecord, workbook); + } + else + { + return null; + } + } - /** - * @return - font formatting object if defined, null otherwise - */ - public HSSFFontFormatting getFontFormatting() - { - return getFontFormatting(false); - } - /** - * create a new font formatting structure if it does not exist, - * otherwise just return existing object. - * @return - font formatting object, never returns null. - */ - public HSSFFontFormatting createFontFormatting() - { - return getFontFormatting(true); - } + /** + * @return - font formatting object if defined, null otherwise + */ + public HSSFFontFormatting getFontFormatting() + { + return getFontFormatting(false); + } + /** + * create a new font formatting structure if it does not exist, + * otherwise just return existing object. + * @return - font formatting object, never returns null. + */ + public HSSFFontFormatting createFontFormatting() + { + return getFontFormatting(true); + } - private HSSFBorderFormatting getBorderFormatting(boolean create) - { - BorderFormatting borderFormatting = cfRuleRecord.getBorderFormatting(); - if ( borderFormatting != null) - { - cfRuleRecord.setBorderFormatting(borderFormatting); - return new HSSFBorderFormatting(cfRuleRecord); - } - else if( create ) - { - borderFormatting = new BorderFormatting(); - cfRuleRecord.setBorderFormatting(borderFormatting); - return new HSSFBorderFormatting(cfRuleRecord); - } - else - { - return null; - } - } - /** - * @return - border formatting object if defined, null otherwise - */ - public HSSFBorderFormatting getBorderFormatting() - { - return getBorderFormatting(false); - } - /** - * create a new border formatting structure if it does not exist, - * otherwise just return existing object. - * @return - border formatting object, never returns null. - */ - public HSSFBorderFormatting createBorderFormatting() - { - return getBorderFormatting(true); - } + private HSSFBorderFormatting getBorderFormatting(boolean create) + { + BorderFormatting borderFormatting = cfRuleRecord.getBorderFormatting(); + if ( borderFormatting != null) + { + cfRuleRecord.setBorderFormatting(borderFormatting); + return new HSSFBorderFormatting(cfRuleRecord, workbook); + } + else if( create ) + { + borderFormatting = new BorderFormatting(); + cfRuleRecord.setBorderFormatting(borderFormatting); + return new HSSFBorderFormatting(cfRuleRecord, workbook); + } + else + { + return null; + } + } + /** + * @return - border formatting object if defined, null otherwise + */ + public HSSFBorderFormatting getBorderFormatting() + { + return getBorderFormatting(false); + } + /** + * create a new border formatting structure if it does not exist, + * otherwise just return existing object. + * @return - border formatting object, never returns null. + */ + public HSSFBorderFormatting createBorderFormatting() + { + return getBorderFormatting(true); + } - private HSSFPatternFormatting getPatternFormatting(boolean create) - { - PatternFormatting patternFormatting = cfRuleRecord.getPatternFormatting(); - if ( patternFormatting != null) - { - cfRuleRecord.setPatternFormatting(patternFormatting); - return new HSSFPatternFormatting(cfRuleRecord); - } - else if( create ) - { - patternFormatting = new PatternFormatting(); - cfRuleRecord.setPatternFormatting(patternFormatting); - return new HSSFPatternFormatting(cfRuleRecord); - } - else - { - return null; - } - } + private HSSFPatternFormatting getPatternFormatting(boolean create) + { + PatternFormatting patternFormatting = cfRuleRecord.getPatternFormatting(); + if ( patternFormatting != null) + { + cfRuleRecord.setPatternFormatting(patternFormatting); + return new HSSFPatternFormatting(cfRuleRecord, workbook); + } + else if( create ) + { + patternFormatting = new PatternFormatting(); + cfRuleRecord.setPatternFormatting(patternFormatting); + return new HSSFPatternFormatting(cfRuleRecord, workbook); + } + else + { + return null; + } + } - /** - * @return - pattern formatting object if defined, null otherwise - */ - public HSSFPatternFormatting getPatternFormatting() - { - return getPatternFormatting(false); - } - /** - * create a new pattern formatting structure if it does not exist, - * otherwise just return existing object. - * @return - pattern formatting object, never returns null. - */ - public HSSFPatternFormatting createPatternFormatting() - { - return getPatternFormatting(true); - } + /** + * @return - pattern formatting object if defined, null otherwise + */ + public HSSFPatternFormatting getPatternFormatting() + { + return getPatternFormatting(false); + } + /** + * create a new pattern formatting structure if it does not exist, + * otherwise just return existing object. + * @return - pattern formatting object, never returns null. + */ + public HSSFPatternFormatting createPatternFormatting() + { + return getPatternFormatting(true); + } + + private HSSFIconMultiStateFormatting getMultiStateFormatting(boolean create) { + if (cfRuleRecord instanceof CFRule12Record) { + // Good + } else { + if (create) throw new IllegalArgumentException("Can't convert a CF into a CF12 record"); + return null; + } + CFRule12Record cfRule12Record = (CFRule12Record)cfRuleRecord; + IconMultiStateFormatting iconFormatting = cfRule12Record.getMultiStateFormatting(); + if (iconFormatting != null) + { + return new HSSFIconMultiStateFormatting(cfRule12Record, sheet); + } + else if( create ) + { + iconFormatting = cfRule12Record.createMultiStateFormatting(); + return new HSSFIconMultiStateFormatting(cfRule12Record, sheet); + } + else + { + return null; + } + } + + /** + * @return icon / multi-state formatting object if defined, null otherwise + */ + public HSSFIconMultiStateFormatting getMultiStateFormatting() { + return getMultiStateFormatting(false); + } - /** - * @return - the conditiontype for the cfrule - */ - public byte getConditionType() { - return cfRuleRecord.getConditionType(); - } + /** + * create a new icon / multi-state formatting object if it does not exist, + * otherwise just return the existing object. + */ + public HSSFIconMultiStateFormatting createMultiStateFormatting() { + return getMultiStateFormatting(true); + } + + /** + * @return - the conditiontype for the cfrule + */ + public byte getConditionType() { + return cfRuleRecord.getConditionType(); + } + /** + * @return - the conditiontype for the cfrule + */ + public ConditionType getConditionTypeType() { + return ConditionType.forId(getConditionType()); + } - /** - * @return - the comparisionoperatation for the cfrule - */ - public byte getComparisonOperation() { - return cfRuleRecord.getComparisonOperation(); - } + /** + * @return - the comparisionoperatation for the cfrule + */ + public byte getComparisonOperation() { + return cfRuleRecord.getComparisonOperation(); + } - public String getFormula1() - { - return toFormulaString(cfRuleRecord.getParsedExpression1()); - } + public String getFormula1() + { + return toFormulaString(cfRuleRecord.getParsedExpression1()); + } - public String getFormula2() - { - byte conditionType = cfRuleRecord.getConditionType(); - if (conditionType == CELL_COMPARISON) { - byte comparisonOperation = cfRuleRecord.getComparisonOperation(); - switch(comparisonOperation) - { - case ComparisonOperator.BETWEEN: - case ComparisonOperator.NOT_BETWEEN: - return toFormulaString(cfRuleRecord.getParsedExpression2()); - } - } - return null; - } + public String getFormula2() { + byte conditionType = cfRuleRecord.getConditionType(); + if (conditionType == CELL_COMPARISON) { + byte comparisonOperation = cfRuleRecord.getComparisonOperation(); + switch(comparisonOperation) { + case ComparisonOperator.BETWEEN: + case ComparisonOperator.NOT_BETWEEN: + return toFormulaString(cfRuleRecord.getParsedExpression2()); + } + } + return null; + } - private String toFormulaString(Ptg[] parsedExpression) - { - if(parsedExpression ==null) { - return null; - } - return HSSFFormulaParser.toFormulaString(workbook, parsedExpression); - } + protected String toFormulaString(Ptg[] parsedExpression) { + return toFormulaString(parsedExpression, workbook); + } + protected static String toFormulaString(Ptg[] parsedExpression, HSSFWorkbook workbook) { + if(parsedExpression == null || parsedExpression.length == 0) { + return null; + } + return HSSFFormulaParser.toFormulaString(workbook, parsedExpression); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingThreshold.java b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingThreshold.java new file mode 100644 index 000000000..4ab124c05 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFConditionalFormattingThreshold.java @@ -0,0 +1,63 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.usermodel; + +import static org.apache.poi.hssf.record.CFRuleBase.parseFormula; +import static org.apache.poi.hssf.usermodel.HSSFConditionalFormattingRule.toFormulaString; + +import org.apache.poi.hssf.record.cf.Threshold; + +/** + * High level representation for Icon / Multi-State / Databar / + * Colour Scale change thresholds + */ +public final class HSSFConditionalFormattingThreshold implements org.apache.poi.ss.usermodel.ConditionalFormattingThreshold { + private final Threshold threshold; + private final HSSFSheet sheet; + private final HSSFWorkbook workbook; + + protected HSSFConditionalFormattingThreshold(Threshold threshold, HSSFSheet sheet) { + this.threshold = threshold; + this.sheet = sheet; + this.workbook = sheet.getWorkbook(); + } + protected Threshold getThreshold() { + return threshold; + } + + public RangeType getRangeType() { + return RangeType.byId(threshold.getType()); + } + public void setRangeType(RangeType type) { + threshold.setType((byte)type.id); + } + + public String getFormula() { + return toFormulaString(threshold.getParsedExpression(), workbook); + } + public void setFormula(String formula) { + threshold.setParsedExpression(parseFormula(formula, sheet)); + } + + public Double getValue() { + return threshold.getValue(); + } + public void setValue(Double value) { + threshold.setValue(value); + } +} diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java index 598ea9c02..07f5fd472 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFontFormatting.java @@ -17,382 +17,388 @@ package org.apache.poi.hssf.usermodel; -import org.apache.poi.hssf.record.CFRuleRecord; +import org.apache.poi.hssf.record.CFRuleBase; import org.apache.poi.hssf.record.cf.FontFormatting; +import org.apache.poi.hssf.util.HSSFColor; +import org.apache.poi.ss.usermodel.Color; /** * High level representation for Font Formatting component * of Conditional Formatting settings */ -public final class HSSFFontFormatting implements org.apache.poi.ss.usermodel.FontFormatting -{ +public final class HSSFFontFormatting implements org.apache.poi.ss.usermodel.FontFormatting { + /** Underline type - None */ + public final static byte U_NONE = FontFormatting.U_NONE; + /** Underline type - Single */ + public final static byte U_SINGLE = FontFormatting.U_SINGLE; + /** Underline type - Double */ + public final static byte U_DOUBLE = FontFormatting.U_DOUBLE; + /** Underline type - Single Accounting */ + public final static byte U_SINGLE_ACCOUNTING = FontFormatting.U_SINGLE_ACCOUNTING; + /** Underline type - Double Accounting */ + public final static byte U_DOUBLE_ACCOUNTING = FontFormatting.U_DOUBLE_ACCOUNTING; - /** Underline type - None */ - public final static byte U_NONE = FontFormatting.U_NONE; - /** Underline type - Single */ - public final static byte U_SINGLE = FontFormatting.U_SINGLE; - /** Underline type - Double */ - public final static byte U_DOUBLE = FontFormatting.U_DOUBLE; - /** Underline type - Single Accounting */ - public final static byte U_SINGLE_ACCOUNTING = FontFormatting.U_SINGLE_ACCOUNTING; - /** Underline type - Double Accounting */ - public final static byte U_DOUBLE_ACCOUNTING = FontFormatting.U_DOUBLE_ACCOUNTING; + private final FontFormatting fontFormatting; + private final HSSFWorkbook workbook; - private final FontFormatting fontFormatting; - - protected HSSFFontFormatting(CFRuleRecord cfRuleRecord) - { - this.fontFormatting = cfRuleRecord.getFontFormatting(); - } - - protected FontFormatting getFontFormattingBlock() - { - return fontFormatting; - } + protected HSSFFontFormatting(CFRuleBase cfRuleRecord, HSSFWorkbook workbook) { + this.fontFormatting = cfRuleRecord.getFontFormatting(); + this.workbook = workbook; + } - /** - * get the type of super or subscript for the font - * - * @return super or subscript option - * @see #SS_NONE - * @see #SS_SUPER - * @see #SS_SUB - */ - public short getEscapementType() - { - return fontFormatting.getEscapementType(); - } + protected FontFormatting getFontFormattingBlock() { + return fontFormatting; + } - /** - * @return font color index - */ - public short getFontColorIndex() - { - return fontFormatting.getFontColorIndex(); - } + /** + * get the type of super or subscript for the font + * + * @return super or subscript option + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + public short getEscapementType() + { + return fontFormatting.getEscapementType(); + } - /** - * gets the height of the font in 1/20th point units - * - * @return fontheight (in points/20); or -1 if not modified - */ - public int getFontHeight() - { - return fontFormatting.getFontHeight(); - } + /** + * @return font color index + */ + public short getFontColorIndex() + { + return fontFormatting.getFontColorIndex(); + } - /** - * get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is - * 0x190 for normal and 0x2bc for bold - * - * @return bw - a number between 100-1000 for the fonts "boldness" - */ + public HSSFColor getFontColor() { + return workbook.getCustomPalette().getColor( + getFontColorIndex() + ); + } - public short getFontWeight() - { - return fontFormatting.getFontWeight(); - } + public void setFontColor(Color color) { + HSSFColor hcolor = HSSFColor.toHSSFColor(color); + if (hcolor == null) { + fontFormatting.setFontColorIndex((short)0); + } else { + fontFormatting.setFontColorIndex(hcolor.getIndex()); + } + } - /** - * @see org.apache.poi.hssf.record.cf.FontFormatting#getRawRecord() - */ - protected byte[] getRawRecord() - { - return fontFormatting.getRawRecord(); - } + /** + * gets the height of the font in 1/20th point units + * + * @return fontheight (in points/20); or -1 if not modified + */ + public int getFontHeight() { + return fontFormatting.getFontHeight(); + } - /** - * get the type of underlining for the font - * - * @return font underlining type - * - * @see #U_NONE - * @see #U_SINGLE - * @see #U_DOUBLE - * @see #U_SINGLE_ACCOUNTING - * @see #U_DOUBLE_ACCOUNTING - */ - public short getUnderlineType() - { - return fontFormatting.getUnderlineType(); - } + /** + * get the font weight for this font (100-1000dec or 0x64-0x3e8). Default is + * 0x190 for normal and 0x2bc for bold + * + * @return bw - a number between 100-1000 for the fonts "boldness" + */ + public short getFontWeight() { + return fontFormatting.getFontWeight(); + } - /** - * get whether the font weight is set to bold or not - * - * @return bold - whether the font is bold or not - */ - public boolean isBold() - { - return fontFormatting.isFontWeightModified() && fontFormatting.isBold(); - } + /** + * @see org.apache.poi.hssf.record.cf.FontFormatting#getRawRecord() + */ + protected byte[] getRawRecord() { + return fontFormatting.getRawRecord(); + } - /** - * @return true if escapement type was modified from default - */ - public boolean isEscapementTypeModified() - { - return fontFormatting.isEscapementTypeModified(); - } + /** + * get the type of underlining for the font + * + * @return font underlining type + * + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + public short getUnderlineType() + { + return fontFormatting.getUnderlineType(); + } - /** - * @return true if font cancellation was modified from default - */ - public boolean isFontCancellationModified() - { - return fontFormatting.isFontCancellationModified(); - } + /** + * get whether the font weight is set to bold or not + * + * @return bold - whether the font is bold or not + */ + public boolean isBold() + { + return fontFormatting.isFontWeightModified() && fontFormatting.isBold(); + } - /** - * @return true if font outline type was modified from default - */ - public boolean isFontOutlineModified() - { - return fontFormatting.isFontOutlineModified(); - } + /** + * @return true if escapement type was modified from default + */ + public boolean isEscapementTypeModified() + { + return fontFormatting.isEscapementTypeModified(); + } - /** - * @return true if font shadow type was modified from default - */ - public boolean isFontShadowModified() - { - return fontFormatting.isFontShadowModified(); - } + /** + * @return true if font cancellation was modified from default + */ + public boolean isFontCancellationModified() + { + return fontFormatting.isFontCancellationModified(); + } - /** - * @return true if font style was modified from default - */ - public boolean isFontStyleModified() - { - return fontFormatting.isFontStyleModified(); - } + /** + * @return true if font outline type was modified from default + */ + public boolean isFontOutlineModified() + { + return fontFormatting.isFontOutlineModified(); + } - /** - * @return true if font style was set to italic - */ - public boolean isItalic() - { - return fontFormatting.isFontStyleModified() && fontFormatting.isItalic(); - } + /** + * @return true if font shadow type was modified from default + */ + public boolean isFontShadowModified() + { + return fontFormatting.isFontShadowModified(); + } - /** - * @return true if font outline is on - */ - public boolean isOutlineOn() - { - return fontFormatting.isFontOutlineModified() && fontFormatting.isOutlineOn(); - } + /** + * @return true if font style was modified from default + */ + public boolean isFontStyleModified() + { + return fontFormatting.isFontStyleModified(); + } - /** - * @return true if font shadow is on - */ - public boolean isShadowOn() - { - return fontFormatting.isFontOutlineModified() && fontFormatting.isShadowOn(); - } + /** + * @return true if font style was set to italic + */ + public boolean isItalic() + { + return fontFormatting.isFontStyleModified() && fontFormatting.isItalic(); + } - /** - * @return true if font strikeout is on - */ - public boolean isStruckout() - { - return fontFormatting.isFontCancellationModified() && fontFormatting.isStruckout(); - } + /** + * @return true if font outline is on + */ + public boolean isOutlineOn() + { + return fontFormatting.isFontOutlineModified() && fontFormatting.isOutlineOn(); + } - /** - * @return true if font underline type was modified from default - */ - public boolean isUnderlineTypeModified() - { - return fontFormatting.isUnderlineTypeModified(); - } + /** + * @return true if font shadow is on + */ + public boolean isShadowOn() + { + return fontFormatting.isFontOutlineModified() && fontFormatting.isShadowOn(); + } - /** - * @return true if font weight was modified from default - */ - public boolean isFontWeightModified() - { - return fontFormatting.isFontWeightModified(); - } + /** + * @return true if font strikeout is on + */ + public boolean isStruckout() + { + return fontFormatting.isFontCancellationModified() && fontFormatting.isStruckout(); + } - /** - * set font style options. - * - * @param italic - if true, set posture style to italic, otherwise to normal - * @param bold if true, set font weight to bold, otherwise to normal - */ - - public void setFontStyle(boolean italic, boolean bold) - { - boolean modified = italic || bold; - fontFormatting.setItalic(italic); - fontFormatting.setBold(bold); - fontFormatting.setFontStyleModified(modified); - fontFormatting.setFontWieghtModified(modified); - } + /** + * @return true if font underline type was modified from default + */ + public boolean isUnderlineTypeModified() + { + return fontFormatting.isUnderlineTypeModified(); + } - /** - * set font style options to default values (non-italic, non-bold) - */ - public void resetFontStyle() - { - setFontStyle(false,false); - } + /** + * @return true if font weight was modified from default + */ + public boolean isFontWeightModified() + { + return fontFormatting.isFontWeightModified(); + } - /** - * set the escapement type for the font - * - * @param escapementType super or subscript option - * @see #SS_NONE - * @see #SS_SUPER - * @see #SS_SUB - */ - public void setEscapementType(short escapementType) - { - switch(escapementType) - { - case HSSFFontFormatting.SS_SUB: - case HSSFFontFormatting.SS_SUPER: - fontFormatting.setEscapementType(escapementType); - fontFormatting.setEscapementTypeModified(true); - break; - case HSSFFontFormatting.SS_NONE: - fontFormatting.setEscapementType(escapementType); - fontFormatting.setEscapementTypeModified(false); - break; - default: - } - } + /** + * set font style options. + * + * @param italic - if true, set posture style to italic, otherwise to normal + * @param bold if true, set font weight to bold, otherwise to normal + */ - /** - * @param modified - * @see org.apache.poi.hssf.record.cf.FontFormatting#setEscapementTypeModified(boolean) - */ - public void setEscapementTypeModified(boolean modified) - { - fontFormatting.setEscapementTypeModified(modified); - } + public void setFontStyle(boolean italic, boolean bold) + { + boolean modified = italic || bold; + fontFormatting.setItalic(italic); + fontFormatting.setBold(bold); + fontFormatting.setFontStyleModified(modified); + fontFormatting.setFontWieghtModified(modified); + } - /** - * @param modified - * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontCancellationModified(boolean) - */ - public void setFontCancellationModified(boolean modified) - { - fontFormatting.setFontCancellationModified(modified); - } + /** + * set font style options to default values (non-italic, non-bold) + */ + public void resetFontStyle() + { + setFontStyle(false,false); + } - /** - * @param fci - * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontColorIndex(short) - */ - public void setFontColorIndex(short fci) - { - fontFormatting.setFontColorIndex(fci); - } + /** + * set the escapement type for the font + * + * @param escapementType super or subscript option + * @see #SS_NONE + * @see #SS_SUPER + * @see #SS_SUB + */ + public void setEscapementType(short escapementType) { + switch(escapementType) { + case HSSFFontFormatting.SS_SUB: + case HSSFFontFormatting.SS_SUPER: + fontFormatting.setEscapementType(escapementType); + fontFormatting.setEscapementTypeModified(true); + break; + case HSSFFontFormatting.SS_NONE: + fontFormatting.setEscapementType(escapementType); + fontFormatting.setEscapementTypeModified(false); + break; + default: + } + } - /** - * @param height - * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontHeight(int) - */ - public void setFontHeight(int height) - { - fontFormatting.setFontHeight(height); - } + /** + * @param modified + * @see org.apache.poi.hssf.record.cf.FontFormatting#setEscapementTypeModified(boolean) + */ + public void setEscapementTypeModified(boolean modified) { + fontFormatting.setEscapementTypeModified(modified); + } - /** - * @param modified - * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontOutlineModified(boolean) - */ - public void setFontOutlineModified(boolean modified) - { - fontFormatting.setFontOutlineModified(modified); - } + /** + * @param modified + * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontCancellationModified(boolean) + */ + public void setFontCancellationModified(boolean modified) + { + fontFormatting.setFontCancellationModified(modified); + } - /** - * @param modified - * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontShadowModified(boolean) - */ - public void setFontShadowModified(boolean modified) - { - fontFormatting.setFontShadowModified(modified); - } + /** + * @param fci + * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontColorIndex(short) + */ + public void setFontColorIndex(short fci) + { + fontFormatting.setFontColorIndex(fci); + } - /** - * @param modified - * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontStyleModified(boolean) - */ - public void setFontStyleModified(boolean modified) - { - fontFormatting.setFontStyleModified(modified); - } + /** + * @param height + * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontHeight(int) + */ + public void setFontHeight(int height) + { + fontFormatting.setFontHeight(height); + } - /** - * @param on - * @see org.apache.poi.hssf.record.cf.FontFormatting#setOutline(boolean) - */ - public void setOutline(boolean on) - { - fontFormatting.setOutline(on); - fontFormatting.setFontOutlineModified(on); - } + /** + * @param modified + * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontOutlineModified(boolean) + */ + public void setFontOutlineModified(boolean modified) + { + fontFormatting.setFontOutlineModified(modified); + } - /** - * @param on - * @see org.apache.poi.hssf.record.cf.FontFormatting#setShadow(boolean) - */ - public void setShadow(boolean on) - { - fontFormatting.setShadow(on); - fontFormatting.setFontShadowModified(on); - } + /** + * @param modified + * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontShadowModified(boolean) + */ + public void setFontShadowModified(boolean modified) + { + fontFormatting.setFontShadowModified(modified); + } - /** - * @param strike - * @see org.apache.poi.hssf.record.cf.FontFormatting#setStrikeout(boolean) - */ - public void setStrikeout(boolean strike) - { - fontFormatting.setStrikeout(strike); - fontFormatting.setFontCancellationModified(strike); - } + /** + * @param modified + * @see org.apache.poi.hssf.record.cf.FontFormatting#setFontStyleModified(boolean) + */ + public void setFontStyleModified(boolean modified) + { + fontFormatting.setFontStyleModified(modified); + } - /** - * set the type of underlining type for the font - * - * @param underlineType super or subscript option - * - * @see #U_NONE - * @see #U_SINGLE - * @see #U_DOUBLE - * @see #U_SINGLE_ACCOUNTING - * @see #U_DOUBLE_ACCOUNTING - */ - public void setUnderlineType(short underlineType) - { - switch(underlineType) - { - case HSSFFontFormatting.U_SINGLE: - case HSSFFontFormatting.U_DOUBLE: - case HSSFFontFormatting.U_SINGLE_ACCOUNTING: - case HSSFFontFormatting.U_DOUBLE_ACCOUNTING: - fontFormatting.setUnderlineType(underlineType); - setUnderlineTypeModified(true); - break; - - case HSSFFontFormatting.U_NONE: - fontFormatting.setUnderlineType(underlineType); - setUnderlineTypeModified(false); - break; - default: - } - } + /** + * @param on + * @see org.apache.poi.hssf.record.cf.FontFormatting#setOutline(boolean) + */ + public void setOutline(boolean on) + { + fontFormatting.setOutline(on); + fontFormatting.setFontOutlineModified(on); + } - /** - * @param modified - * @see org.apache.poi.hssf.record.cf.FontFormatting#setUnderlineTypeModified(boolean) - */ - public void setUnderlineTypeModified(boolean modified) - { - fontFormatting.setUnderlineTypeModified(modified); - } + /** + * @param on + * @see org.apache.poi.hssf.record.cf.FontFormatting#setShadow(boolean) + */ + public void setShadow(boolean on) + { + fontFormatting.setShadow(on); + fontFormatting.setFontShadowModified(on); + } + + /** + * @param strike + * @see org.apache.poi.hssf.record.cf.FontFormatting#setStrikeout(boolean) + */ + public void setStrikeout(boolean strike) + { + fontFormatting.setStrikeout(strike); + fontFormatting.setFontCancellationModified(strike); + } + + /** + * set the type of underlining type for the font + * + * @param underlineType super or subscript option + * + * @see #U_NONE + * @see #U_SINGLE + * @see #U_DOUBLE + * @see #U_SINGLE_ACCOUNTING + * @see #U_DOUBLE_ACCOUNTING + */ + public void setUnderlineType(short underlineType) { + switch(underlineType) { + case HSSFFontFormatting.U_SINGLE: + case HSSFFontFormatting.U_DOUBLE: + case HSSFFontFormatting.U_SINGLE_ACCOUNTING: + case HSSFFontFormatting.U_DOUBLE_ACCOUNTING: + fontFormatting.setUnderlineType(underlineType); + setUnderlineTypeModified(true); + break; + + case HSSFFontFormatting.U_NONE: + fontFormatting.setUnderlineType(underlineType); + setUnderlineTypeModified(false); + break; + default: + } + } + + /** + * @param modified + * @see org.apache.poi.hssf.record.cf.FontFormatting#setUnderlineTypeModified(boolean) + */ + public void setUnderlineTypeModified(boolean modified) + { + fontFormatting.setUnderlineTypeModified(modified); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFIconMultiStateFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFIconMultiStateFormatting.java new file mode 100644 index 000000000..e93d5c918 --- /dev/null +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFIconMultiStateFormatting.java @@ -0,0 +1,81 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hssf.usermodel; + +import org.apache.poi.hssf.record.CFRule12Record; +import org.apache.poi.hssf.record.cf.IconMultiStateFormatting; +import org.apache.poi.hssf.record.cf.Threshold; +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold; + +/** + * High level representation for Icon / Multi-State Formatting + * component of Conditional Formatting settings + */ +public final class HSSFIconMultiStateFormatting implements org.apache.poi.ss.usermodel.IconMultiStateFormatting { + private final HSSFSheet sheet; + private final CFRule12Record cfRule12Record; + private final IconMultiStateFormatting iconFormatting; + + protected HSSFIconMultiStateFormatting(CFRule12Record cfRule12Record, HSSFSheet sheet) { + this.sheet = sheet; + this.cfRule12Record = cfRule12Record; + this.iconFormatting = this.cfRule12Record.getMultiStateFormatting(); + } + + public IconSet getIconSet() { + return iconFormatting.getIconSet(); + } + public void setIconSet(IconSet set) { + iconFormatting.setIconSet(set); + } + + public boolean isIconOnly() { + return iconFormatting.isIconOnly(); + } + public void setIconOnly(boolean only) { + iconFormatting.setIconOnly(only); + } + + public boolean isReversed() { + return iconFormatting.isReversed(); + } + public void setReversed(boolean reversed) { + iconFormatting.setReversed(reversed); + } + + public HSSFConditionalFormattingThreshold[] getThresholds() { + Threshold[] t = iconFormatting.getThresholds(); + HSSFConditionalFormattingThreshold[] ht = new HSSFConditionalFormattingThreshold[t.length]; + for (int i=0; i getMergedRegions() { + List addresses = new ArrayList(); + for (int i=0; i < _sheet.getNumMergedRegions(); i++) { + addresses.add(_sheet.getMergedRegionAt(i)); + } + return addresses; + } + /** * @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not * be the third row if say for instance the second row is undefined. diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java index ce6bf76b6..deca836a0 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheetConditionalFormatting.java @@ -17,142 +17,156 @@ package org.apache.poi.hssf.usermodel; +import org.apache.poi.hssf.record.CFRule12Record; +import org.apache.poi.hssf.record.CFRuleBase; import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate; import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.ConditionalFormatting; import org.apache.poi.ss.usermodel.ConditionalFormattingRule; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.usermodel.SheetConditionalFormatting; import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.SpreadsheetVersion; /** * The 'Conditional Formatting' facet of HSSFSheet */ public final class HSSFSheetConditionalFormatting implements SheetConditionalFormatting { + private final HSSFSheet _sheet; + private final ConditionalFormattingTable _conditionalFormattingTable; - private final HSSFSheet _sheet; - private final ConditionalFormattingTable _conditionalFormattingTable; + /* package */ HSSFSheetConditionalFormatting(HSSFSheet sheet) { + _sheet = sheet; + _conditionalFormattingTable = sheet.getSheet().getConditionalFormattingTable(); + } - /* package */ HSSFSheetConditionalFormatting(HSSFSheet sheet) { - _sheet = sheet; - _conditionalFormattingTable = sheet.getSheet().getConditionalFormattingTable(); - } - - /** - * A factory method allowing to create a conditional formatting rule - * with a cell comparison operator

    - * TODO - formulas containing cell references are currently not parsed properly - * - * @param comparisonOperation - a constant value from - * {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator}:

    - *

      - *
    • BETWEEN
    • - *
    • NOT_BETWEEN
    • - *
    • EQUAL
    • - *
    • NOT_EQUAL
    • - *
    • GT
    • - *
    • LT
    • - *
    • GE
    • - *
    • LE
    • - *
    - *

    - * @param formula1 - formula for the valued, compared with the cell - * @param formula2 - second formula (only used with - * {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#BETWEEN}) and - * {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#NOT_BETWEEN} operations) - */ - public HSSFConditionalFormattingRule createConditionalFormattingRule( - byte comparisonOperation, - String formula1, - String formula2) { - - HSSFWorkbook wb = _sheet.getWorkbook(); - CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, formula2); - return new HSSFConditionalFormattingRule(wb, rr); - } + /** + * A factory method allowing to create a conditional formatting rule + * with a cell comparison operator

    + * TODO - formulas containing cell references are currently not parsed properly + * + * @param comparisonOperation - a constant value from + * {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator}:

    + *

      + *
    • BETWEEN
    • + *
    • NOT_BETWEEN
    • + *
    • EQUAL
    • + *
    • NOT_EQUAL
    • + *
    • GT
    • + *
    • LT
    • + *
    • GE
    • + *
    • LE
    • + *
    + *

    + * @param formula1 - formula for the valued, compared with the cell + * @param formula2 - second formula (only used with + * {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#BETWEEN}) and + * {@link org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator#NOT_BETWEEN} operations) + */ + public HSSFConditionalFormattingRule createConditionalFormattingRule( + byte comparisonOperation, + String formula1, + String formula2) { + CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, formula2); + return new HSSFConditionalFormattingRule(_sheet, rr); + } public HSSFConditionalFormattingRule createConditionalFormattingRule( byte comparisonOperation, String formula1) { - - HSSFWorkbook wb = _sheet.getWorkbook(); CFRuleRecord rr = CFRuleRecord.create(_sheet, comparisonOperation, formula1, null); - return new HSSFConditionalFormattingRule(wb, rr); + return new HSSFConditionalFormattingRule(_sheet, rr); } - /** - * A factory method allowing to create a conditional formatting rule with a formula.
    - * - * The formatting rules are applied by Excel when the value of the formula not equal to 0.

    - * TODO - formulas containing cell references are currently not parsed properly - * @param formula - formula for the valued, compared with the cell - */ - public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) { - HSSFWorkbook wb = _sheet.getWorkbook(); - CFRuleRecord rr = CFRuleRecord.create(_sheet, formula); - return new HSSFConditionalFormattingRule(wb, rr); - } + /** + * A factory method allowing to create a conditional formatting rule with a formula.
    + * + * The formatting rules are applied by Excel when the value of the formula not equal to 0.

    + * TODO - formulas containing cell references are currently not parsed properly + * @param formula - formula for the valued, compared with the cell + */ + public HSSFConditionalFormattingRule createConditionalFormattingRule(String formula) { + CFRuleRecord rr = CFRuleRecord.create(_sheet, formula); + return new HSSFConditionalFormattingRule(_sheet, rr); + } - /** - * Adds a copy of HSSFConditionalFormatting object to the sheet - *

    This method could be used to copy HSSFConditionalFormatting object - * from one sheet to another. For example: - *

    -	 * HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
    -	 * newSheet.addConditionalFormatting(cf);
    -	 * 
    - * - * @param cf HSSFConditionalFormatting object - * @return index of the new Conditional Formatting object - */ - public int addConditionalFormatting( HSSFConditionalFormatting cf ) { - CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate(); + /** + * A factory method allowing the creation of conditional formatting + * rules using an Icon Set / Multi-State formatting. + * The thresholds for it will be created, but will be empty + * and require configuring with + * {@link HSSFConditionalFormattingRule#getMultiStateFormatting()} + * then + * {@link HSSFIconMultiStateFormatting#getThresholds()} + */ + public HSSFConditionalFormattingRule createConditionalFormattingRule( + IconSet iconSet) { + CFRule12Record rr = CFRule12Record.create(_sheet, iconSet); + return new HSSFConditionalFormattingRule(_sheet, rr); + } - return _conditionalFormattingTable.add(cfraClone); - } + // TODO Support types beyond CELL_VALUE_IS and FORMULA and ICONs + + /** + * Adds a copy of HSSFConditionalFormatting object to the sheet + *

    This method could be used to copy HSSFConditionalFormatting object + * from one sheet to another. For example: + *

    +     * HSSFConditionalFormatting cf = sheet.getConditionalFormattingAt(index);
    +     * newSheet.addConditionalFormatting(cf);
    +     * 
    + * + * @param cf HSSFConditionalFormatting object + * @return index of the new Conditional Formatting object + */ + public int addConditionalFormatting( HSSFConditionalFormatting cf ) { + CFRecordsAggregate cfraClone = cf.getCFRecordsAggregate().cloneCFAggregate(); + + return _conditionalFormattingTable.add(cfraClone); + } public int addConditionalFormatting( ConditionalFormatting cf ) { return addConditionalFormatting((HSSFConditionalFormatting)cf); } - /** - * @deprecated use CellRangeAddress instead of Region - */ - public int addConditionalFormatting(org.apache.poi.ss.util.Region[] regions, HSSFConditionalFormattingRule[] cfRules) { - return addConditionalFormatting(org.apache.poi.ss.util.Region.convertRegionsToCellRanges(regions), cfRules); - } - /** - * Allows to add a new Conditional Formatting set to the sheet. - * - * @param regions - list of rectangular regions to apply conditional formatting rules - * @param cfRules - set of up to three conditional formatting rules - * - * @return index of the newly created Conditional Formatting object - */ - public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) { - if (regions == null) { - throw new IllegalArgumentException("regions must not be null"); - } - for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97); + /** + * @deprecated use CellRangeAddress instead of Region + */ + public int addConditionalFormatting(org.apache.poi.ss.util.Region[] regions, HSSFConditionalFormattingRule[] cfRules) { + return addConditionalFormatting(org.apache.poi.ss.util.Region.convertRegionsToCellRanges(regions), cfRules); + } + /** + * Allows to add a new Conditional Formatting set to the sheet. + * + * @param regions - list of rectangular regions to apply conditional formatting rules + * @param cfRules - set of up to three conditional formatting rules + * + * @return index of the newly created Conditional Formatting object + */ + public int addConditionalFormatting(CellRangeAddress[] regions, HSSFConditionalFormattingRule[] cfRules) { + if (regions == null) { + throw new IllegalArgumentException("regions must not be null"); + } + for(CellRangeAddress range : regions) range.validate(SpreadsheetVersion.EXCEL97); - if (cfRules == null) { - throw new IllegalArgumentException("cfRules must not be null"); - } - if (cfRules.length == 0) { - throw new IllegalArgumentException("cfRules must not be empty"); - } - if (cfRules.length > 3) { - throw new IllegalArgumentException("Number of rules must not exceed 3"); - } + if (cfRules == null) { + throw new IllegalArgumentException("cfRules must not be null"); + } + if (cfRules.length == 0) { + throw new IllegalArgumentException("cfRules must not be empty"); + } + if (cfRules.length > 3) { + throw new IllegalArgumentException("Number of rules must not exceed 3"); + } - CFRuleRecord[] rules = new CFRuleRecord[cfRules.length]; - for (int i = 0; i != cfRules.length; i++) { - rules[i] = cfRules[i].getCfRuleRecord(); - } - CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules); - return _conditionalFormattingTable.add(cfra); - } + CFRuleBase[] rules = new CFRuleBase[cfRules.length]; + for (int i = 0; i != cfRules.length; i++) { + rules[i] = cfRules[i].getCfRuleRecord(); + } + CFRecordsAggregate cfra = new CFRecordsAggregate(regions, rules); + return _conditionalFormattingTable.add(cfra); + } public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) { HSSFConditionalFormattingRule[] hfRules; @@ -164,70 +178,61 @@ public final class HSSFSheetConditionalFormatting implements SheetConditionalFor return addConditionalFormatting(regions, hfRules); } - public int addConditionalFormatting(CellRangeAddress[] regions, - HSSFConditionalFormattingRule rule1) - { - return addConditionalFormatting(regions, - rule1 == null ? null : new HSSFConditionalFormattingRule[] - { - rule1 - }); - } + public int addConditionalFormatting(CellRangeAddress[] regions, + HSSFConditionalFormattingRule rule1) { + return addConditionalFormatting(regions, rule1 == null ? + null : new HSSFConditionalFormattingRule[] { rule1 } + ); + } public int addConditionalFormatting(CellRangeAddress[] regions, - ConditionalFormattingRule rule1) - { + ConditionalFormattingRule rule1) { return addConditionalFormatting(regions, (HSSFConditionalFormattingRule)rule1); } - public int addConditionalFormatting(CellRangeAddress[] regions, - HSSFConditionalFormattingRule rule1, - HSSFConditionalFormattingRule rule2) - { - return addConditionalFormatting(regions, - new HSSFConditionalFormattingRule[] - { - rule1, rule2 - }); - } + public int addConditionalFormatting(CellRangeAddress[] regions, + HSSFConditionalFormattingRule rule1, + HSSFConditionalFormattingRule rule2) { + return addConditionalFormatting(regions, + new HSSFConditionalFormattingRule[] { rule1, rule2 }); + } public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule rule1, - ConditionalFormattingRule rule2) - { + ConditionalFormattingRule rule2) { return addConditionalFormatting(regions, (HSSFConditionalFormattingRule)rule1, (HSSFConditionalFormattingRule)rule2 - ); + ); } - /** - * gets Conditional Formatting object at a particular index - * - * @param index - * of the Conditional Formatting object to fetch - * @return Conditional Formatting object - */ - public HSSFConditionalFormatting getConditionalFormattingAt(int index) { - CFRecordsAggregate cf = _conditionalFormattingTable.get(index); - if (cf == null) { - return null; - } - return new HSSFConditionalFormatting(_sheet.getWorkbook(), cf); - } + /** + * gets Conditional Formatting object at a particular index + * + * @param index + * of the Conditional Formatting object to fetch + * @return Conditional Formatting object + */ + public HSSFConditionalFormatting getConditionalFormattingAt(int index) { + CFRecordsAggregate cf = _conditionalFormattingTable.get(index); + if (cf == null) { + return null; + } + return new HSSFConditionalFormatting(_sheet, cf); + } - /** - * @return number of Conditional Formatting objects of the sheet - */ - public int getNumConditionalFormattings() { - return _conditionalFormattingTable.size(); - } + /** + * @return number of Conditional Formatting objects of the sheet + */ + public int getNumConditionalFormattings() { + return _conditionalFormattingTable.size(); + } - /** - * removes a Conditional Formatting object by index - * @param index of a Conditional Formatting object to remove - */ - public void removeConditionalFormatting(int index) { - _conditionalFormattingTable.remove(index); - } + /** + * removes a Conditional Formatting object by index + * @param index of a Conditional Formatting object to remove + */ + public void removeConditionalFormatting(int index) { + _conditionalFormattingTable.remove(index); + } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 503ed64d6..65ec1a33e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -65,6 +65,7 @@ import org.apache.poi.hssf.record.UnknownRecord; import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor; import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.util.CellReference; +import org.apache.poi.poifs.crypt.Decryptor; import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.EntryUtils; @@ -205,6 +206,19 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss public HSSFWorkbook(POIFSFileSystem fs) throws IOException { this(fs,true); } + /** + * Given a POI POIFSFileSystem object, read in its Workbook along + * with all related nodes, and populate the high and low level models. + *

    This calls {@link #HSSFWorkbook(POIFSFileSystem, boolean)} with + * preserve nodes set to true. + * + * @see #HSSFWorkbook(POIFSFileSystem, boolean) + * @see org.apache.poi.poifs.filesystem.POIFSFileSystem + * @exception IOException if the stream cannot be read + */ + public HSSFWorkbook(NPOIFSFileSystem fs) throws IOException { + this(fs.getRoot(),true); + } /** * Given a POI POIFSFileSystem object, read in its Workbook and populate @@ -248,7 +262,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss // check for an encrypted .xlsx file - they get OLE2 wrapped try { - directory.getEntry("EncryptedPackage"); + directory.getEntry(Decryptor.DEFAULT_POIFS_ENTRY); throw new EncryptedDocumentException("The supplied spreadsheet seems to be an Encrypted .xlsx file. " + "It must be decrypted before use by XSSF, it cannot be used by HSSF"); } catch (FileNotFoundException e) { @@ -378,7 +392,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss public HSSFWorkbook(InputStream s, boolean preserveNodes) throws IOException { - this(new POIFSFileSystem(s), preserveNodes); + this(new NPOIFSFileSystem(s).getRoot(), preserveNodes); } /** @@ -1276,7 +1290,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss throws IOException { byte[] bytes = getBytes(); - POIFSFileSystem fs = new POIFSFileSystem(); + NPOIFSFileSystem fs = new NPOIFSFileSystem(); // For tracking what we've written out, used if we're // going to be preserving nodes @@ -1843,7 +1857,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss throws IOException { // check if we were created by POIFS otherwise create a new dummy POIFS for storing the package data if (directory == null) { - directory = new POIFSFileSystem().getRoot(); + directory = new NPOIFSFileSystem().getRoot(); preserveNodes = true; } diff --git a/src/java/org/apache/poi/hssf/util/HSSFColor.java b/src/java/org/apache/poi/hssf/util/HSSFColor.java index f438e1b00..d7a1cb587 100644 --- a/src/java/org/apache/poi/hssf/util/HSSFColor.java +++ b/src/java/org/apache/poi/hssf/util/HSSFColor.java @@ -204,6 +204,13 @@ public class HSSFColor implements Color { { return BLACK.hexString; } + + public static HSSFColor toHSSFColor(Color color) { + if (color != null && !(color instanceof HSSFColor)) { + throw new IllegalArgumentException("Only HSSFColor objects are supported"); + } + return (HSSFColor)color; + } /** * Class BLACK diff --git a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java index 8a2bf0045..2c5716d2a 100644 --- a/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java +++ b/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java @@ -16,6 +16,8 @@ ==================================================================== */ package org.apache.poi.poifs.crypt; +import static org.apache.poi.poifs.crypt.Decryptor.DEFAULT_POIFS_ENTRY; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -132,8 +134,8 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream { super.close(); int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE); - calculateChecksum(fileOut, oleStreamSize); - dir.createDocument("EncryptedPackage", oleStreamSize, new EncryptedPackageWriter()); + calculateChecksum(fileOut, (int)_pos); + dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, new EncryptedPackageWriter()); createEncryptionInfoEntry(dir, fileOut); } catch (GeneralSecurityException e) { throw new IOException(e); diff --git a/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java b/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java index 0c80c6c2b..f6477fb9b 100644 --- a/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java +++ b/src/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java @@ -36,7 +36,7 @@ public class DataSpaceMapUtils { public static void addDefaultDataSpace(DirectoryEntry dir) throws IOException { DataSpaceMapEntry dsme = new DataSpaceMapEntry( new int[]{ 0 } - , new String[]{ "EncryptedPackage" } + , new String[]{ Decryptor.DEFAULT_POIFS_ENTRY } , "StrongEncryptionDataSpace" ); DataSpaceMap dsm = new DataSpaceMap(new DataSpaceMapEntry[]{dsme}); diff --git a/src/java/org/apache/poi/poifs/crypt/Decryptor.java b/src/java/org/apache/poi/poifs/crypt/Decryptor.java index af449290e..eb94dca98 100644 --- a/src/java/org/apache/poi/poifs/crypt/Decryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/Decryptor.java @@ -25,10 +25,12 @@ import javax.crypto.SecretKey; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; public abstract class Decryptor { public static final String DEFAULT_PASSWORD="VelvetSweatshop"; + public static final String DEFAULT_POIFS_ENTRY="EncryptedPackage"; protected final EncryptionInfoBuilder builder; private SecretKey secretKey; @@ -83,7 +85,9 @@ public abstract class Decryptor { public InputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException { return getDataStream(fs.getRoot()); } - + public InputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException { + return getDataStream(fs.getRoot()); + } public InputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException { return getDataStream(fs.getRoot()); } diff --git a/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java b/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java index 0418befe2..3aafb90ca 100644 --- a/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java +++ b/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java @@ -26,6 +26,7 @@ import java.io.IOException; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; @@ -68,14 +69,27 @@ public class EncryptionInfo { public static BitField flagAES = BitFieldFactory.getInstance(0x20); + /** + * Opens for decryption + */ public EncryptionInfo(POIFSFileSystem fs) throws IOException { this(fs.getRoot()); } - + /** + * Opens for decryption + */ + public EncryptionInfo(OPOIFSFileSystem fs) throws IOException { + this(fs.getRoot()); + } + /** + * Opens for decryption + */ public EncryptionInfo(NPOIFSFileSystem fs) throws IOException { this(fs.getRoot()); } - + /** + * Opens for decryption + */ public EncryptionInfo(DirectoryNode dir) throws IOException { this(dir.createDocumentInputStream("EncryptionInfo"), false); } @@ -131,7 +145,7 @@ public class EncryptionInfo { } /** - * @deprecated use constructor without fs parameter + * @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (fs parameter no longer required) */ @Deprecated public EncryptionInfo(POIFSFileSystem fs, EncryptionMode encryptionMode) { @@ -139,7 +153,7 @@ public class EncryptionInfo { } /** - * @deprecated use constructor without fs parameter + * @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (fs parameter no longer required) */ @Deprecated public EncryptionInfo(NPOIFSFileSystem fs, EncryptionMode encryptionMode) { @@ -147,7 +161,7 @@ public class EncryptionInfo { } /** - * @deprecated use constructor without dir parameter + * @deprecated Use {@link #EncryptionInfo(EncryptionMode)} (dir parameter no longer required) */ @Deprecated public EncryptionInfo(DirectoryNode dir, EncryptionMode encryptionMode) { @@ -155,7 +169,7 @@ public class EncryptionInfo { } /** - * @deprecated use constructor without fs parameter + * @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)} */ @Deprecated public EncryptionInfo( @@ -171,7 +185,7 @@ public class EncryptionInfo { } /** - * @deprecated use constructor without fs parameter + * @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)} */ @Deprecated public EncryptionInfo( @@ -187,7 +201,7 @@ public class EncryptionInfo { } /** - * @deprecated use constructor without dir parameter + * @deprecated use {@link #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode)} */ @Deprecated public EncryptionInfo( @@ -202,6 +216,11 @@ public class EncryptionInfo { this(encryptionMode, cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode); } + /** + * Prepares for encryption, using the given Encryption Mode, and + * all other parameters as default. + * @see #EncryptionInfo(EncryptionMode, CipherAlgorithm, HashAlgorithm, int, int, ChainingMode) + */ public EncryptionInfo(EncryptionMode encryptionMode) { this(encryptionMode, null, null, -1, -1, null); } diff --git a/src/java/org/apache/poi/poifs/crypt/Encryptor.java b/src/java/org/apache/poi/poifs/crypt/Encryptor.java index abfd69330..d40f8ae5d 100644 --- a/src/java/org/apache/poi/poifs/crypt/Encryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/Encryptor.java @@ -24,9 +24,11 @@ import javax.crypto.SecretKey; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; public abstract class Encryptor { + protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY; private SecretKey secretKey; /** @@ -50,7 +52,9 @@ public abstract class Encryptor { public OutputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException { return getDataStream(fs.getRoot()); } - + public OutputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException { + return getDataStream(fs.getRoot()); + } public OutputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException { return getDataStream(fs.getRoot()); } diff --git a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java index 40eab54e3..a2d3d6f0e 100644 --- a/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java @@ -118,7 +118,7 @@ public class BinaryRC4Decryptor extends Decryptor { public InputStream getDataStream(DirectoryNode dir) throws IOException, GeneralSecurityException { - DocumentInputStream dis = dir.createDocumentInputStream("EncryptedPackage"); + DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY); _length = dis.readLong(); BinaryRC4CipherInputStream cipherStream = new BinaryRC4CipherInputStream(dis, _length); return cipherStream; @@ -131,4 +131,4 @@ public class BinaryRC4Decryptor extends Decryptor { return _length; } -} \ No newline at end of file +} diff --git a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java index c1ae13cee..1e470d726 100644 --- a/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java @@ -40,7 +40,7 @@ import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentInputStream; import org.apache.poi.poifs.filesystem.DocumentNode; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.util.BitField; import org.apache.poi.util.BitFieldFactory; import org.apache.poi.util.BoundedInputStream; @@ -200,7 +200,7 @@ public class CryptoAPIDecryptor extends Decryptor { @SuppressWarnings("unused") public InputStream getDataStream(DirectoryNode dir) throws IOException, GeneralSecurityException { - POIFSFileSystem fsOut = new POIFSFileSystem(); + NPOIFSFileSystem fsOut = new NPOIFSFileSystem(); DocumentNode es = (DocumentNode) dir.getEntry("EncryptedSummary"); DocumentInputStream dis = dir.createDocumentInputStream(es); ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -240,6 +240,7 @@ public class CryptoAPIDecryptor extends Decryptor { sbis = null; bos.reset(); fsOut.writeFilesystem(bos); + fsOut.close(); _length = bos.size(); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); return bis; diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java index 2b2c75b52..1d6ddd398 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java @@ -123,7 +123,7 @@ public class StandardDecryptor extends Decryptor { } public InputStream getDataStream(DirectoryNode dir) throws IOException { - DocumentInputStream dis = dir.createDocumentInputStream("EncryptedPackage"); + DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY); _length = dis.readLong(); diff --git a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java index 7049c715d..ae6304fbb 100644 --- a/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java +++ b/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java @@ -166,7 +166,7 @@ public class StandardEncryptor extends Encryptor { void writeToPOIFS() throws IOException { int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE); - dir.createDocument("EncryptedPackage", oleStreamSize, this); + dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, this); // TODO: any properties??? } diff --git a/src/java/org/apache/poi/poifs/dev/POIFSDump.java b/src/java/org/apache/poi/poifs/dev/POIFSDump.java index ace19d8d1..ce7d9e441 100644 --- a/src/java/org/apache/poi/poifs/dev/POIFSDump.java +++ b/src/java/org/apache/poi/poifs/dev/POIFSDump.java @@ -16,27 +16,54 @@ ==================================================================== */ package org.apache.poi.poifs.dev; -import org.apache.poi.poifs.filesystem.*; - -import java.io.FileInputStream; import java.io.File; -import java.io.IOException; +import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.nio.ByteBuffer; import java.util.Iterator; +import org.apache.poi.poifs.common.POIFSConstants; +import org.apache.poi.poifs.filesystem.DirectoryEntry; +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.poifs.filesystem.DocumentNode; +import org.apache.poi.poifs.filesystem.Entry; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSStream; +import org.apache.poi.poifs.property.NPropertyTable; +import org.apache.poi.poifs.storage.HeaderBlock; + /** - * * Dump internal structure of a OLE2 file into file system - * - * @author Yegor Kozlov */ public class POIFSDump { - public static void main(String[] args) throws Exception { + if (args.length == 0) { + System.err.println("Must specify at least one file to dump"); + System.exit(1); + } + + boolean dumpProps = false, dumpMini = false; for (int i = 0; i < args.length; i++) { + if (args[i].equalsIgnoreCase("-dumprops") || + args[i].equalsIgnoreCase("-dump-props") || + args[i].equalsIgnoreCase("-dump-properties")) { + dumpProps = true; + continue; + } + if (args[i].equalsIgnoreCase("-dumpmini") || + args[i].equalsIgnoreCase("-dump-mini") || + args[i].equalsIgnoreCase("-dump-ministream") || + args[i].equalsIgnoreCase("-dump-mini-stream")) { + dumpMini = true; + continue; + } + System.out.println("Dumping " + args[i]); FileInputStream is = new FileInputStream(args[i]); - POIFSFileSystem fs = new POIFSFileSystem(is); + NPOIFSFileSystem fs = new NPOIFSFileSystem(is); is.close(); DirectoryEntry root = fs.getRoot(); @@ -44,13 +71,39 @@ public class POIFSDump { file.mkdir(); dump(root, file); + + if (dumpProps) { + HeaderBlock header = getHeaderBlock(fs); + dump(fs, header.getPropertyStart(), "properties", file); + } + if (dumpMini) { + NPropertyTable props = getPropertyTable(fs); + int startBlock = props.getRoot().getStartBlock(); + if (startBlock == POIFSConstants.END_OF_CHAIN) { + System.err.println("No Mini Stream in file"); + } else { + dump(fs, startBlock, "mini-stream", file); + } + } } } - + + protected static HeaderBlock getHeaderBlock(NPOIFSFileSystem fs) throws Exception { + Field headerF = NPOIFSFileSystem.class.getDeclaredField("_header"); + headerF.setAccessible(true); + HeaderBlock header = (HeaderBlock)headerF.get(fs); + return header; + } + protected static NPropertyTable getPropertyTable(NPOIFSFileSystem fs) throws Exception { + Field ptF = NPOIFSFileSystem.class.getDeclaredField("_property_table"); + ptF.setAccessible(true); + NPropertyTable table = (NPropertyTable)ptF.get(fs); + return table; + } public static void dump(DirectoryEntry root, File parent) throws IOException { - for(Iterator it = root.getEntries(); it.hasNext();){ - Entry entry = (Entry)it.next(); + for(Iterator it = root.getEntries(); it.hasNext();){ + Entry entry = it.next(); if(entry instanceof DocumentNode){ DocumentNode node = (DocumentNode)entry; DocumentInputStream is = new DocumentInputStream(node); @@ -58,9 +111,12 @@ public class POIFSDump { is.read(bytes); is.close(); - FileOutputStream out = new FileOutputStream(new File(parent, node.getName().trim())); - out.write(bytes); - out.close(); + OutputStream out = new FileOutputStream(new File(parent, node.getName().trim())); + try { + out.write(bytes); + } finally { + out.close(); + } } else if (entry instanceof DirectoryEntry){ DirectoryEntry dir = (DirectoryEntry)entry; File file = new File(parent, entry.getName()); @@ -71,4 +127,17 @@ public class POIFSDump { } } } + public static void dump(NPOIFSFileSystem fs, int startBlock, String name, File parent) throws IOException { + File file = new File(parent, name); + FileOutputStream out = new FileOutputStream(file); + NPOIFSStream stream = new NPOIFSStream(fs, startBlock); + + byte[] b = new byte[fs.getBigBlockSize()]; + for (ByteBuffer bb : stream) { + int len = bb.remaining(); + bb.get(b); + out.write(b, 0, len); + } + out.close(); + } } diff --git a/src/java/org/apache/poi/poifs/dev/POIFSHeaderDumper.java b/src/java/org/apache/poi/poifs/dev/POIFSHeaderDumper.java index 78ed986a4..e321c8b9b 100644 --- a/src/java/org/apache/poi/poifs/dev/POIFSHeaderDumper.java +++ b/src/java/org/apache/poi/poifs/dev/POIFSHeaderDumper.java @@ -24,9 +24,10 @@ import java.lang.reflect.Method; import org.apache.poi.poifs.common.POIFSBigBlockSize; import org.apache.poi.poifs.common.POIFSConstants; +import org.apache.poi.poifs.property.DirectoryProperty; +import org.apache.poi.poifs.property.Property; import org.apache.poi.poifs.property.PropertyTable; import org.apache.poi.poifs.storage.BlockAllocationTableReader; -import org.apache.poi.poifs.storage.BlockList; import org.apache.poi.poifs.storage.HeaderBlock; import org.apache.poi.poifs.storage.ListManagedBlock; import org.apache.poi.poifs.storage.RawDataBlockList; @@ -42,111 +43,146 @@ import org.apache.poi.util.IntList; * down the source of corruption in a file. */ public class POIFSHeaderDumper { - /** - * Display the entries of multiple POIFS files - * - * @param args the names of the files to be displayed - */ - public static void main(final String args[]) throws Exception { - if (args.length == 0) { - System.err.println("Must specify at least one file to view"); - System.exit(1); - } + /** + * Display the entries of multiple POIFS files + * + * @param args the names of the files to be displayed + */ + public static void main(final String args[]) throws Exception { + if (args.length == 0) { + System.err.println("Must specify at least one file to view"); + System.exit(1); + } - for (int j = 0; j < args.length; j++) { - viewFile(args[j]); - } - } + for (int j = 0; j < args.length; j++) { + viewFile(args[j]); + } + } - public static void viewFile(final String filename) throws Exception { - InputStream inp = new FileInputStream(filename); - - // Header - HeaderBlock header_block = new HeaderBlock(inp); - displayHeader(header_block); - - // Raw blocks - POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize(); - RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize); - displayRawBlocksSummary(data_blocks); - - // Main FAT Table - BlockAllocationTableReader batReader = - new BlockAllocationTableReader( - header_block.getBigBlockSize(), - header_block.getBATCount(), - header_block.getBATArray(), - header_block.getXBATCount(), - header_block.getXBATIndex(), - data_blocks); - displayBATReader(batReader); + public static void viewFile(final String filename) throws Exception { + System.out.println("Dumping headers from: " + filename); + InputStream inp = new FileInputStream(filename); - // Properties Table - PropertyTable properties = - new PropertyTable(header_block, data_blocks); - - // Mini Fat - BlockList sbat = - SmallBlockTableReader.getSmallDocumentBlocks( - bigBlockSize, data_blocks, properties.getRoot(), - header_block.getSBATStart() - ); - } + // Header + HeaderBlock header_block = new HeaderBlock(inp); + displayHeader(header_block); - public static void displayHeader(HeaderBlock header_block) throws Exception { - System.out.println("Header Details:"); - System.out.println(" Block size: " + header_block.getBigBlockSize().getBigBlockSize()); - System.out.println(" BAT (FAT) header blocks: " + header_block.getBATArray().length); - System.out.println(" BAT (FAT) block count: " + header_block.getBATCount()); - System.out.println(" XBAT (FAT) block count: " + header_block.getXBATCount()); - System.out.println(" XBAT (FAT) block 1 at: " + header_block.getXBATIndex()); - System.out.println(" SBAT (MiniFAT) block count: " + header_block.getSBATCount()); - System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block.getSBATStart()); - System.out.println(" Property table at: " + header_block.getPropertyStart()); - System.out.println(""); - } + // Raw blocks + POIFSBigBlockSize bigBlockSize = header_block.getBigBlockSize(); + RawDataBlockList data_blocks = new RawDataBlockList(inp, bigBlockSize); + displayRawBlocksSummary(data_blocks); - public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception { - System.out.println("Raw Blocks Details:"); - System.out.println(" Number of blocks: " + data_blocks.blockCount()); - - Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class); - gbm.setAccessible(true); - - for(int i=0; i " + bnS); - } - - System.out.println(""); - } + // Main FAT Table + BlockAllocationTableReader batReader = + new BlockAllocationTableReader( + header_block.getBigBlockSize(), + header_block.getBATCount(), + header_block.getBATArray(), + header_block.getXBATCount(), + header_block.getXBATIndex(), + data_blocks); + displayBATReader("Big Blocks", batReader); + + // Properties Table + PropertyTable properties = + new PropertyTable(header_block, data_blocks); + + // Mini Fat + BlockAllocationTableReader sbatReader = + SmallBlockTableReader._getSmallDocumentBlockReader( + bigBlockSize, data_blocks, properties.getRoot(), + header_block.getSBATStart() + ); + displayBATReader("Small Blocks", sbatReader); + + // Summary of the properties + displayPropertiesSummary(properties); + } + + public static void displayHeader(HeaderBlock header_block) throws Exception { + System.out.println("Header Details:"); + System.out.println(" Block size: " + header_block.getBigBlockSize().getBigBlockSize()); + System.out.println(" BAT (FAT) header blocks: " + header_block.getBATArray().length); + System.out.println(" BAT (FAT) block count: " + header_block.getBATCount()); + if (header_block.getBATCount() > 0) + System.out.println(" BAT (FAT) block 1 at: " + header_block.getBATArray()[0]); + System.out.println(" XBAT (FAT) block count: " + header_block.getXBATCount()); + System.out.println(" XBAT (FAT) block 1 at: " + header_block.getXBATIndex()); + System.out.println(" SBAT (MiniFAT) block count: " + header_block.getSBATCount()); + System.out.println(" SBAT (MiniFAT) block 1 at: " + header_block.getSBATStart()); + System.out.println(" Property table at: " + header_block.getPropertyStart()); + System.out.println(""); + } + + public static void displayRawBlocksSummary(RawDataBlockList data_blocks) throws Exception { + System.out.println("Raw Blocks Details:"); + System.out.println(" Number of blocks: " + data_blocks.blockCount()); + + Method gbm = data_blocks.getClass().getSuperclass().getDeclaredMethod("get", int.class); + gbm.setAccessible(true); + + for(int i=0; i " + bnS); + } + + System.out.println(""); + } + + public static void displayPropertiesSummary(PropertyTable properties) { + System.out.println("Mini Stream starts at " + properties.getRoot().getStartBlock()); + System.out.println("Mini Stream length is " + properties.getRoot().getSize()); + System.out.println(); + + System.out.println("Properties and their block start:"); + displayProperties(properties.getRoot(), ""); + System.out.println(""); + } + public static void displayProperties(DirectoryProperty prop, String indent) { + String nextIndent = indent + " "; + System.out.println(indent + "-> " + prop.getName()); + for (Property cp : prop) { + if (cp instanceof DirectoryProperty) { + displayProperties((DirectoryProperty)cp, nextIndent); + } else { + System.out.println(nextIndent + "=> " + cp.getName()); + System.out.print(nextIndent + " " + cp.getSize() + " bytes in "); + if (cp.shouldUseSmallBlocks()) { + System.out.print("mini"); + } else { + System.out.print("main"); + } + System.out.println(" stream, starts at " + cp.getStartBlock()); + } + } + } } diff --git a/src/java/org/apache/poi/poifs/dev/POIFSViewer.java b/src/java/org/apache/poi/poifs/dev/POIFSViewer.java index 8b8173426..4614376db 100644 --- a/src/java/org/apache/poi/poifs/dev/POIFSViewer.java +++ b/src/java/org/apache/poi/poifs/dev/POIFSViewer.java @@ -19,12 +19,12 @@ package org.apache.poi.poifs.dev; -import java.io.FileInputStream; +import java.io.File; import java.io.IOException; import java.util.Iterator; import java.util.List; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; /** * A simple viewer for POIFS files @@ -76,10 +76,10 @@ public class POIFSViewer try { POIFSViewable fs = - new POIFSFileSystem(new FileInputStream(filename)); - List strings = POIFSViewEngine.inspectViewable(fs, true, + new NPOIFSFileSystem(new File(filename)); + List strings = POIFSViewEngine.inspectViewable(fs, true, 0, " "); - Iterator iter = strings.iterator(); + Iterator iter = strings.iterator(); while (iter.hasNext()) { diff --git a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java index 567527523..a28870918 100644 --- a/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java +++ b/src/java/org/apache/poi/poifs/eventfilesystem/POIFSReader.java @@ -24,7 +24,7 @@ import java.io.*; import java.util.*; import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.poifs.filesystem.POIFSDocument; +import org.apache.poi.poifs.filesystem.OPOIFSDocument; import org.apache.poi.poifs.filesystem.POIFSDocumentPath; import org.apache.poi.poifs.property.DirectoryProperty; import org.apache.poi.poifs.property.Property; @@ -240,19 +240,19 @@ public class POIFSReader if (listeners.hasNext()) { - int size = property.getSize(); - POIFSDocument document = null; + int size = property.getSize(); + OPOIFSDocument document = null; if (property.shouldUseSmallBlocks()) { document = - new POIFSDocument(name, small_blocks + new OPOIFSDocument(name, small_blocks .fetchBlocks(startBlock, -1), size); } else { document = - new POIFSDocument(name, big_blocks + new OPOIFSDocument(name, big_blocks .fetchBlocks(startBlock, -1), size); } while (listeners.hasNext()) diff --git a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java index 8d39bbfa2..9be71a5cc 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java +++ b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java @@ -37,8 +37,6 @@ import org.apache.poi.poifs.property.Property; /** * Simple implementation of DirectoryEntry - * - * @author Marc Johnson (mjohnson at apache dot org) */ public class DirectoryNode extends EntryNode @@ -50,9 +48,9 @@ public class DirectoryNode // Our list of entries, kept sorted to preserve order private ArrayList _entries; - // Only one of these two will exist - // the POIFSFileSystem we belong to - private POIFSFileSystem _ofilesystem; + // Only one of these two will exist + // the OPOIFSFileSystem we belong to + private OPOIFSFileSystem _ofilesystem; // the NPOIFSFileSytem we belong to private NPOIFSFileSystem _nfilesystem; @@ -64,11 +62,11 @@ public class DirectoryNode * is intended strictly for the internal use of this package * * @param property the DirectoryProperty for this DirectoryEntry - * @param filesystem the POIFSFileSystem we belong to + * @param filesystem the OPOIFSFileSystem we belong to * @param parent the parent of this entry */ DirectoryNode(final DirectoryProperty property, - final POIFSFileSystem filesystem, + final OPOIFSFileSystem filesystem, final DirectoryNode parent) { this(property, parent, filesystem, (NPOIFSFileSystem)null); @@ -86,12 +84,12 @@ public class DirectoryNode final NPOIFSFileSystem nfilesystem, final DirectoryNode parent) { - this(property, parent, (POIFSFileSystem)null, nfilesystem); + this(property, parent, (OPOIFSFileSystem)null, nfilesystem); } private DirectoryNode(final DirectoryProperty property, final DirectoryNode parent, - final POIFSFileSystem ofilesystem, + final OPOIFSFileSystem ofilesystem, final NPOIFSFileSystem nfilesystem) { super(property, parent); @@ -148,12 +146,24 @@ public class DirectoryNode /** * @return the filesystem that this belongs to */ - public POIFSFileSystem getFileSystem() + public NPOIFSFileSystem getFileSystem() + { + return _nfilesystem; + } + + /** + * If this is OPOIFS based, return the NPOIFSFileSystem + * that this belong to, otherwise Null if NPOIFS based + * @return the filesystem that this belongs to + */ + public OPOIFSFileSystem getOFileSystem() { return _ofilesystem; } /** + * If this is NPOIFS based, return the NPOIFSFileSystem + * that this belong to, otherwise Null if OPOIFS based * @return the filesystem that this belongs to */ public NPOIFSFileSystem getNFileSystem() @@ -210,7 +220,7 @@ public class DirectoryNode * * @exception IOException */ - DocumentEntry createDocument(final POIFSDocument document) + DocumentEntry createDocument(final OPOIFSDocument document) throws IOException { DocumentProperty property = document.getDocumentProperty(); @@ -411,7 +421,7 @@ public class DirectoryNode if(_nfilesystem != null) { return createDocument(new NPOIFSDocument(name, _nfilesystem, stream)); } else { - return createDocument(new POIFSDocument(name, stream)); + return createDocument(new OPOIFSDocument(name, stream)); } } @@ -434,7 +444,7 @@ public class DirectoryNode if(_nfilesystem != null) { return createDocument(new NPOIFSDocument(name, size, _nfilesystem, writer)); } else { - return createDocument(new POIFSDocument(name, size, _path, writer)); + return createDocument(new OPOIFSDocument(name, size, _path, writer)); } } diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java index 6c6b6100c..82959c7ff 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java @@ -58,7 +58,7 @@ public class DocumentInputStream extends InputStream implements LittleEndianInpu if(documentNode.getDocument() != null) { delegate = new ODocumentInputStream(document); - } else if(parentNode.getFileSystem() != null) { + } else if(parentNode.getOFileSystem() != null) { delegate = new ODocumentInputStream(document); } else if(parentNode.getNFileSystem() != null) { delegate = new NDocumentInputStream(document); @@ -72,7 +72,7 @@ public class DocumentInputStream extends InputStream implements LittleEndianInpu * * @param document the Document to be read */ - public DocumentInputStream(POIFSDocument document) { + public DocumentInputStream(OPOIFSDocument document) { delegate = new ODocumentInputStream(document); } diff --git a/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java b/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java index 9caafb766..7a5bf6900 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java +++ b/src/java/org/apache/poi/poifs/filesystem/DocumentNode.java @@ -27,18 +27,15 @@ import org.apache.poi.poifs.dev.POIFSViewable; import org.apache.poi.poifs.property.DocumentProperty; /** - * Simple implementation of DocumentEntry - * - * @author Marc Johnson (mjohnson at apache dot org) + * Simple implementation of DocumentEntry for OPOIFS */ - public class DocumentNode extends EntryNode implements DocumentEntry, POIFSViewable { // underlying POIFSDocument instance - private POIFSDocument _document; + private OPOIFSDocument _document; /** * create a DocumentNode. This method is not public by design; it @@ -59,8 +56,7 @@ public class DocumentNode * * @return the internal POIFSDocument */ - - POIFSDocument getDocument() + OPOIFSDocument getDocument() { return _document; } diff --git a/src/java/org/apache/poi/poifs/filesystem/EntryUtils.java b/src/java/org/apache/poi/poifs/filesystem/EntryUtils.java index 4bce0641a..d8a55563a 100644 --- a/src/java/org/apache/poi/poifs/filesystem/EntryUtils.java +++ b/src/java/org/apache/poi/poifs/filesystem/EntryUtils.java @@ -124,8 +124,21 @@ public class EntryUtils * @param target * is the target POIFS to copy to */ - public static void copyNodes( POIFSFileSystem source, - POIFSFileSystem target ) throws IOException + public static void copyNodes( OPOIFSFileSystem source, + OPOIFSFileSystem target ) throws IOException + { + copyNodes( source.getRoot(), target.getRoot() ); + } + /** + * Copies all nodes from one POIFS to the other + * + * @param source + * is the source POIFS to copy from + * @param target + * is the target POIFS to copy to + */ + public static void copyNodes( NPOIFSFileSystem source, + NPOIFSFileSystem target ) throws IOException { copyNodes( source.getRoot(), target.getRoot() ); } @@ -140,8 +153,26 @@ public class EntryUtils * @param target is the target POIFS to copy to * @param excepts is a list of Entry Names to be excluded from the copy */ - public static void copyNodes( POIFSFileSystem source, - POIFSFileSystem target, List excepts ) throws IOException + public static void copyNodes( OPOIFSFileSystem source, + OPOIFSFileSystem target, List excepts ) throws IOException + { + copyNodes( + new FilteringDirectoryNode(source.getRoot(), excepts), + new FilteringDirectoryNode(target.getRoot(), excepts) + ); + } + /** + * Copies nodes from one POIFS to the other, minus the excepts. + * This delegates the filtering work to {@link FilteringDirectoryNode}, + * so excepts can be of the form "NodeToExclude" or + * "FilteringDirectory/ExcludedChildNode" + * + * @param source is the source POIFS to copy from + * @param target is the target POIFS to copy to + * @param excepts is a list of Entry Names to be excluded from the copy + */ + public static void copyNodes( NPOIFSFileSystem source, + NPOIFSFileSystem target, List excepts ) throws IOException { copyNodes( new FilteringDirectoryNode(source.getRoot(), excepts), diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java index 7846ed0df..c94e427b9 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -143,8 +144,17 @@ public final class NPOIFSDocument implements POIFSViewable { os.write(buf, 0, readBytes); } - os.close(); + // Pad to the end of the block with -1s + int usedInBlock = length % _block_size; + if (usedInBlock != 0 && usedInBlock != _block_size) { + int toBlockEnd = _block_size - usedInBlock; + byte[] padding = new byte[toBlockEnd]; + Arrays.fill(padding, (byte)0xFF); + os.write(padding); + } + // Tidy and return the length + os.close(); return length; } diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java index f21f6a39a..c27ba3cd1 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java @@ -36,6 +36,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import org.apache.poi.EmptyFileException; import org.apache.poi.poifs.common.POIFSBigBlockSize; import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.dev.POIFSViewable; @@ -114,17 +115,18 @@ public class NPOIFSFileSystem extends BlockStore { this(true); - // Mark us as having a single empty BAT at offset 0 + // Reserve block 0 for the start of the Properties Table + // Create a single empty BAT, at pop that at offset 1 _header.setBATCount(1); - _header.setBATArray(new int[] { 0 }); + _header.setBATArray(new int[] { 1 }); BATBlock bb = BATBlock.createEmptyBATBlock(bigBlockSize, false); - bb.setOurBlockIndex(0); + bb.setOurBlockIndex(1); _bat_blocks.add(bb); - setNextBlock(0, POIFSConstants.FAT_SECTOR_BLOCK); - setNextBlock(1, POIFSConstants.END_OF_CHAIN); + setNextBlock(0, POIFSConstants.END_OF_CHAIN); + setNextBlock(1, POIFSConstants.FAT_SECTOR_BLOCK); - _property_table.setStartBlock(POIFSConstants.END_OF_CHAIN); + _property_table.setStartBlock(0); } /** @@ -210,6 +212,9 @@ public class NPOIFSFileSystem extends BlockStore try { // Initialize the datasource if (srcFile != null) { + if (srcFile.length() == 0) + throw new EmptyFileException(); + FileBackedDataSource d = new FileBackedDataSource(srcFile, readOnly); channel = d.getChannel(); _data = d; @@ -236,7 +241,10 @@ public class NPOIFSFileSystem extends BlockStore // TODO Decide if we can handle these better whilst // still sticking to the iterator contract if(closeChannelOnError) { - channel.close(); + if (channel != null) { + channel.close(); + channel = null; + } } throw e; } @@ -369,6 +377,15 @@ public class NPOIFSFileSystem extends BlockStore return (signature.get() == HeaderBlockConstants._signature); } + /** + * Checks if the supplied first 8 bytes of a stream / file + * has a POIFS (OLE2) header. + */ + public static boolean hasPOIFSHeader(byte[] header8Bytes) { + LongField signature = new LongField(HeaderBlockConstants._signature_offset, header8Bytes); + return (signature.get() == HeaderBlockConstants._signature); + } + /** * Read and process the PropertiesTable and the * FAT / XFAT blocks, so that we're ready to @@ -420,7 +437,7 @@ public class NPOIFSFileSystem extends BlockStore List sbats = new ArrayList(); _mini_store = new NPOIFSMiniStore(this, _property_table.getRoot(), sbats, _header); nextAt = _header.getSBATStart(); - for(int i=0; i<_header.getSBATCount(); i++) { + for(int i=0; i<_header.getSBATCount() && nextAt != POIFSConstants.END_OF_CHAIN; i++) { loopDetector.claim(nextAt); ByteBuffer fatData = getBlockAt(nextAt); sfat = BATBlock.createBATBlock(bigBlockSize, fatData); @@ -749,6 +766,10 @@ public class NPOIFSFileSystem extends BlockStore * to their backing blocks */ private void syncWithDataSource() throws IOException { + // Mini Stream + SBATs first, as mini-stream details have + // to be stored in the Root Property + _mini_store.syncWithDataSource(); + // Properties NPOIFSStream propStream = new NPOIFSStream(this, _header.getPropertyStart()); _property_table.preWrite(); @@ -769,9 +790,6 @@ public class NPOIFSFileSystem extends BlockStore ByteBuffer block = getBlockAt(bat.getOurBlockIndex()); BlockAllocationTableWriter.writeBlock(bat, block); } - - // SBATs - _mini_store.syncWithDataSource(); } /** diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java index 308ae15c7..b784058bc 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java @@ -242,12 +242,24 @@ public class NPOIFSMiniStore extends BlockStore } /** - * Writes the SBATs to their backing blocks + * Writes the SBATs to their backing blocks, and updates + * the mini-stream size in the properties. Stream size is + * based on full blocks used, not the data within the streams */ protected void syncWithDataSource() throws IOException { - for(BATBlock sbat : _sbat_blocks) { + int blocksUsed = 0; + for (BATBlock sbat : _sbat_blocks) { ByteBuffer block = _filesystem.getBlockAt(sbat.getOurBlockIndex()); BlockAllocationTableWriter.writeBlock(sbat, block); + + if (!sbat.hasFreeSectors()) { + blocksUsed += _filesystem.getBigBlockSizeDetails().getBATEntriesPerBlock(); + } else { + blocksUsed += sbat.getUsedSectors(false); + } } + // Set the size on the root in terms of the number of SBAT blocks + // RootProperty.setSize does the sbat -> bytes conversion for us + _filesystem._get_property_table().getRoot().setSize(blocksUsed); } } diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSStream.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSStream.java index 5d444b8cb..da24fc383 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSStream.java @@ -256,8 +256,10 @@ public class NPOIFSStream implements Iterable NPOIFSStream toFree = new NPOIFSStream(blockStore, nextBlock); toFree.free(loopDetector); - // Mark the end of the stream - blockStore.setNextBlock(prevBlock, POIFSConstants.END_OF_CHAIN); + // Mark the end of the stream, if we have any data + if (prevBlock != POIFSConstants.END_OF_CHAIN) { + blockStore.setNextBlock(prevBlock, POIFSConstants.END_OF_CHAIN); + } } } } diff --git a/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java b/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java index a1bc5da95..858e2d9d9 100644 --- a/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/ODocumentInputStream.java @@ -23,9 +23,7 @@ import org.apache.poi.poifs.storage.DataInputBlock; /** * This class provides methods to read a DocumentEntry managed by a - * {@link POIFSFileSystem} instance. - * - * @author Marc Johnson (mjohnson at apache dot org) + * {@link OPOIFSFileSystem} instance. */ public final class ODocumentInputStream extends DocumentInputStream { /** current offset into the Document */ @@ -41,7 +39,7 @@ public final class ODocumentInputStream extends DocumentInputStream { private boolean _closed; /** the actual Document */ - private POIFSDocument _document; + private OPOIFSDocument _document; /** the data block containing the current stream pointer */ private DataInputBlock _currentBlock; @@ -59,7 +57,7 @@ public final class ODocumentInputStream extends DocumentInputStream { throw new IOException("Cannot open internal document storage"); } DocumentNode documentNode = (DocumentNode)document; - if(documentNode.getDocument() == null) { + if (documentNode.getDocument() == null) { throw new IOException("Cannot open internal document storage"); } @@ -76,7 +74,7 @@ public final class ODocumentInputStream extends DocumentInputStream { * * @param document the Document to be read */ - public ODocumentInputStream(POIFSDocument document) { + public ODocumentInputStream(OPOIFSDocument document) { _current_offset = 0; _marked_offset = 0; _document_size = document.getSize(); diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/OPOIFSDocument.java similarity index 94% rename from src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java rename to src/java/org/apache/poi/poifs/filesystem/OPOIFSDocument.java index c6b35fd88..05b21baea 100644 --- a/src/java/org/apache/poi/poifs/filesystem/POIFSDocument.java +++ b/src/java/org/apache/poi/poifs/filesystem/OPOIFSDocument.java @@ -40,11 +40,10 @@ import org.apache.poi.poifs.storage.SmallDocumentBlock; import org.apache.poi.util.HexDump; /** - * This class manages a document in the POIFS filesystem. - * - * @author Marc Johnson (mjohnson at apache dot org) + * This class manages a document in a old-style + * OPOIFS filesystem. */ -public final class POIFSDocument implements BATManaged, BlockWritable, POIFSViewable { +public final class OPOIFSDocument implements BATManaged, BlockWritable, POIFSViewable { private static final DocumentBlock[] EMPTY_BIG_BLOCK_ARRAY = { }; private static final SmallDocumentBlock[] EMPTY_SMALL_BLOCK_ARRAY = { }; private DocumentProperty _property; @@ -63,7 +62,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView * @param blocks the big blocks making up the POIFSDocument * @param length the actual length of the POIFSDocument */ - public POIFSDocument(String name, RawDataBlock[] blocks, int length) throws IOException { + public OPOIFSDocument(String name, RawDataBlock[] blocks, int length) throws IOException { _size = length; if(blocks.length == 0) { _bigBigBlockSize = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS; @@ -104,7 +103,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView * @param blocks the small blocks making up the POIFSDocument * @param length the actual length of the POIFSDocument */ - public POIFSDocument(String name, SmallDocumentBlock[] blocks, int length) { + public OPOIFSDocument(String name, SmallDocumentBlock[] blocks, int length) { _size = length; if(blocks.length == 0) { @@ -126,7 +125,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView * @param blocks the small blocks making up the POIFSDocument * @param length the actual length of the POIFSDocument */ - public POIFSDocument(String name, POIFSBigBlockSize bigBlockSize, ListManagedBlock[] blocks, int length) throws IOException { + public OPOIFSDocument(String name, POIFSBigBlockSize bigBlockSize, ListManagedBlock[] blocks, int length) throws IOException { _size = length; _bigBigBlockSize = bigBlockSize; _property = new DocumentProperty(name, _size); @@ -139,7 +138,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView _small_store = new SmallBlockStore(bigBlockSize,EMPTY_SMALL_BLOCK_ARRAY); } } - public POIFSDocument(String name, ListManagedBlock[] blocks, int length) throws IOException { + public OPOIFSDocument(String name, ListManagedBlock[] blocks, int length) throws IOException { this(name, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, blocks, length); } @@ -149,7 +148,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView * @param name the name of the POIFSDocument * @param stream the InputStream we read data from */ - public POIFSDocument(String name, POIFSBigBlockSize bigBlockSize, InputStream stream) throws IOException { + public OPOIFSDocument(String name, POIFSBigBlockSize bigBlockSize, InputStream stream) throws IOException { List blocks = new ArrayList(); _size = 0; @@ -178,7 +177,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView _small_store = new SmallBlockStore(bigBlockSize,EMPTY_SMALL_BLOCK_ARRAY); } } - public POIFSDocument(String name, InputStream stream) throws IOException { + public OPOIFSDocument(String name, InputStream stream) throws IOException { this(name, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, stream); } @@ -190,7 +189,7 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView * @param path the path of the POIFSDocument * @param writer the writer who will eventually write the document contents */ - public POIFSDocument(String name, int size, POIFSBigBlockSize bigBlockSize, POIFSDocumentPath path, POIFSWriterListener writer) { + public OPOIFSDocument(String name, int size, POIFSBigBlockSize bigBlockSize, POIFSDocumentPath path, POIFSWriterListener writer) { _size = size; _bigBigBlockSize = bigBlockSize; _property = new DocumentProperty(name, _size); @@ -203,14 +202,14 @@ public final class POIFSDocument implements BATManaged, BlockWritable, POIFSView _big_store = new BigBlockStore(_bigBigBlockSize, path, name, size, writer); } } - public POIFSDocument(String name, int size, POIFSDocumentPath path, POIFSWriterListener writer) { + public OPOIFSDocument(String name, int size, POIFSDocumentPath path, POIFSWriterListener writer) { this(name, size, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, path, writer); } /** * @return array of SmallDocumentBlocks; may be empty, cannot be null */ - public BlockWritable[] getSmallBlocks() { + public SmallDocumentBlock[] getSmallBlocks() { return _small_store.getBlocks(); } diff --git a/src/java/org/apache/poi/poifs/filesystem/OPOIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/OPOIFSFileSystem.java new file mode 100644 index 000000000..19abc48ab --- /dev/null +++ b/src/java/org/apache/poi/poifs/filesystem/OPOIFSFileSystem.java @@ -0,0 +1,607 @@ + +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + + +package org.apache.poi.poifs.filesystem; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.poi.poifs.common.POIFSBigBlockSize; +import org.apache.poi.poifs.common.POIFSConstants; +import org.apache.poi.poifs.dev.POIFSViewable; +import org.apache.poi.poifs.property.DirectoryProperty; +import org.apache.poi.poifs.property.Property; +import org.apache.poi.poifs.property.PropertyTable; +import org.apache.poi.poifs.storage.BATBlock; +import org.apache.poi.poifs.storage.BlockAllocationTableReader; +import org.apache.poi.poifs.storage.BlockAllocationTableWriter; +import org.apache.poi.poifs.storage.BlockList; +import org.apache.poi.poifs.storage.BlockWritable; +import org.apache.poi.poifs.storage.HeaderBlock; +import org.apache.poi.poifs.storage.HeaderBlockConstants; +import org.apache.poi.poifs.storage.HeaderBlockWriter; +import org.apache.poi.poifs.storage.RawDataBlockList; +import org.apache.poi.poifs.storage.SmallBlockTableReader; +import org.apache.poi.poifs.storage.SmallBlockTableWriter; +import org.apache.poi.util.CloseIgnoringInputStream; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.LongField; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + *

    This is the main class of the POIFS system; it manages the entire + * life cycle of the filesystem.

    + *

    This is the older version, which uses more memory, and doesn't + * support in-place writes.

    + */ +public class OPOIFSFileSystem + implements POIFSViewable +{ + private static final POILogger _logger = + POILogFactory.getLogger(OPOIFSFileSystem.class); + + /** + * Convenience method for clients that want to avoid the auto-close behaviour of the constructor. + */ + public static InputStream createNonClosingInputStream(InputStream is) { + return new CloseIgnoringInputStream(is); + } + + private PropertyTable _property_table; + private List _documents; + private DirectoryNode _root; + + /** + * What big block size the file uses. Most files + * use 512 bytes, but a few use 4096 + */ + private POIFSBigBlockSize bigBlockSize = + POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS; + + /** + * Constructor, intended for writing + */ + public OPOIFSFileSystem() + { + HeaderBlock header_block = new HeaderBlock(bigBlockSize); + _property_table = new PropertyTable(header_block); + _documents = new ArrayList(); + _root = null; + } + + /** + * Create a OPOIFSFileSystem from an InputStream. Normally the stream is read until + * EOF. The stream is always closed.

    + * + * Some streams are usable after reaching EOF (typically those that return true + * for markSupported()). In the unlikely case that the caller has such a stream + * and needs to use it after this constructor completes, a work around is to wrap the + * stream in order to trap the close() call. A convenience method ( + * createNonClosingInputStream()) has been provided for this purpose: + *

    +     * InputStream wrappedStream = OPOIFSFileSystem.createNonClosingInputStream(is);
    +     * HSSFWorkbook wb = new HSSFWorkbook(wrappedStream);
    +     * is.reset();
    +     * doSomethingElse(is);
    +     * 
    + * Note also the special case of ByteArrayInputStream for which the close() + * method does nothing. + *
    +     * ByteArrayInputStream bais = ...
    +     * HSSFWorkbook wb = new HSSFWorkbook(bais); // calls bais.close() !
    +     * bais.reset(); // no problem
    +     * doSomethingElse(bais);
    +     * 
    + * + * @param stream the InputStream from which to read the data + * + * @exception IOException on errors reading, or on invalid data + */ + + public OPOIFSFileSystem(InputStream stream) + throws IOException + { + this(); + boolean success = false; + + HeaderBlock header_block; + RawDataBlockList data_blocks; + try { + // read the header block from the stream + header_block = new HeaderBlock(stream); + bigBlockSize = header_block.getBigBlockSize(); + + // read the rest of the stream into blocks + data_blocks = new RawDataBlockList(stream, bigBlockSize); + success = true; + } finally { + closeInputStream(stream, success); + } + + + // set up the block allocation table (necessary for the + // data_blocks to be manageable + new BlockAllocationTableReader(header_block.getBigBlockSize(), + header_block.getBATCount(), + header_block.getBATArray(), + header_block.getXBATCount(), + header_block.getXBATIndex(), + data_blocks); + + // get property table from the document + PropertyTable properties = + new PropertyTable(header_block, data_blocks); + + // init documents + processProperties( + SmallBlockTableReader.getSmallDocumentBlocks( + bigBlockSize, data_blocks, properties.getRoot(), + header_block.getSBATStart() + ), + data_blocks, + properties.getRoot().getChildren(), + null, + header_block.getPropertyStart() + ); + + // For whatever reason CLSID of root is always 0. + getRoot().setStorageClsid(properties.getRoot().getStorageClsid()); + } + /** + * @param stream the stream to be closed + * @param success false if an exception is currently being thrown in the calling method + */ + protected void closeInputStream(InputStream stream, boolean success) { + + if(stream.markSupported() && !(stream instanceof ByteArrayInputStream)) { + String msg = "POIFS is closing the supplied input stream of type (" + + stream.getClass().getName() + ") which supports mark/reset. " + + "This will be a problem for the caller if the stream will still be used. " + + "If that is the case the caller should wrap the input stream to avoid this close logic. " + + "This warning is only temporary and will not be present in future versions of POI."; + _logger.log(POILogger.WARN, msg); + } + try { + stream.close(); + } catch (IOException e) { + if(success) { + throw new RuntimeException(e); + } + // else not success? Try block did not complete normally + // just print stack trace and leave original ex to be thrown + e.printStackTrace(); + } + } + + /** + * Checks that the supplied InputStream (which MUST + * support mark and reset, or be a PushbackInputStream) + * has a POIFS (OLE2) header at the start of it. + * If your InputStream does not support mark / reset, + * then wrap it in a PushBackInputStream, then be + * sure to always use that, and not the original! + * @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream + */ + public static boolean hasPOIFSHeader(InputStream inp) throws IOException { + // We want to peek at the first 8 bytes + byte[] header = IOUtils.peekFirst8Bytes(inp); + return hasPOIFSHeader(header); + } + /** + * Checks if the supplied first 8 bytes of a stream / file + * has a POIFS (OLE2) header. + */ + public static boolean hasPOIFSHeader(byte[] header8Bytes) { + LongField signature = new LongField(HeaderBlockConstants._signature_offset, header8Bytes); + + // Did it match the signature? + return (signature.get() == HeaderBlockConstants._signature); + } + + /** + * Create a new document to be added to the root directory + * + * @param stream the InputStream from which the document's data + * will be obtained + * @param name the name of the new POIFSDocument + * + * @return the new DocumentEntry + * + * @exception IOException on error creating the new POIFSDocument + */ + + public DocumentEntry createDocument(final InputStream stream, + final String name) + throws IOException + { + return getRoot().createDocument(name, stream); + } + + /** + * create a new DocumentEntry in the root entry; the data will be + * provided later + * + * @param name the name of the new DocumentEntry + * @param size the size of the new DocumentEntry + * @param writer the writer of the new DocumentEntry + * + * @return the new DocumentEntry + * + * @exception IOException + */ + + public DocumentEntry createDocument(final String name, final int size, + final POIFSWriterListener writer) + throws IOException + { + return getRoot().createDocument(name, size, writer); + } + + /** + * create a new DirectoryEntry in the root directory + * + * @param name the name of the new DirectoryEntry + * + * @return the new DirectoryEntry + * + * @exception IOException on name duplication + */ + + public DirectoryEntry createDirectory(final String name) + throws IOException + { + return getRoot().createDirectory(name); + } + + /** + * Write the filesystem out + * + * @param stream the OutputStream to which the filesystem will be + * written + * + * @exception IOException thrown on errors writing to the stream + */ + + public void writeFilesystem(final OutputStream stream) + throws IOException + { + + // get the property table ready + _property_table.preWrite(); + + // create the small block store, and the SBAT + SmallBlockTableWriter sbtw = + new SmallBlockTableWriter(bigBlockSize, _documents, _property_table.getRoot()); + + // create the block allocation table + BlockAllocationTableWriter bat = + new BlockAllocationTableWriter(bigBlockSize); + + // create a list of BATManaged objects: the documents plus the + // property table and the small block table + List bm_objects = new ArrayList(); + + bm_objects.addAll(_documents); + bm_objects.add(_property_table); + bm_objects.add(sbtw); + bm_objects.add(sbtw.getSBAT()); + + // walk the list, allocating space for each and assigning each + // a starting block number + Iterator iter = bm_objects.iterator(); + + while (iter.hasNext()) + { + BATManaged bmo = ( BATManaged ) iter.next(); + int block_count = bmo.countBlocks(); + + if (block_count != 0) + { + bmo.setStartBlock(bat.allocateSpace(block_count)); + } + else + { + + // Either the BATManaged object is empty or its data + // is composed of SmallBlocks; in either case, + // allocating space in the BAT is inappropriate + } + } + + // allocate space for the block allocation table and take its + // starting block + int batStartBlock = bat.createBlocks(); + + // get the extended block allocation table blocks + HeaderBlockWriter header_block_writer = new HeaderBlockWriter(bigBlockSize); + BATBlock[] xbat_blocks = + header_block_writer.setBATBlocks(bat.countBlocks(), + batStartBlock); + + // set the property table start block + header_block_writer.setPropertyStart(_property_table.getStartBlock()); + + // set the small block allocation table start block + header_block_writer.setSBATStart(sbtw.getSBAT().getStartBlock()); + + // set the small block allocation table block count + header_block_writer.setSBATBlockCount(sbtw.getSBATBlockCount()); + + // the header is now properly initialized. Make a list of + // writers (the header block, followed by the documents, the + // property table, the small block store, the small block + // allocation table, the block allocation table, and the + // extended block allocation table blocks) + List writers = new ArrayList(); + + writers.add(header_block_writer); + writers.addAll(_documents); + writers.add(_property_table); + writers.add(sbtw); + writers.add(sbtw.getSBAT()); + writers.add(bat); + for (int j = 0; j < xbat_blocks.length; j++) + { + writers.add(xbat_blocks[ j ]); + } + + // now, write everything out + iter = writers.iterator(); + while (iter.hasNext()) + { + BlockWritable writer = ( BlockWritable ) iter.next(); + + writer.writeBlocks(stream); + } + } + + /** + * read in a file and write it back out again + * + * @param args names of the files; arg[ 0 ] is the input file, + * arg[ 1 ] is the output file + * + * @exception IOException + */ + + public static void main(String args[]) + throws IOException + { + if (args.length != 2) + { + System.err.println( + "two arguments required: input filename and output filename"); + System.exit(1); + } + FileInputStream istream = new FileInputStream(args[ 0 ]); + FileOutputStream ostream = new FileOutputStream(args[ 1 ]); + + new OPOIFSFileSystem(istream).writeFilesystem(ostream); + istream.close(); + ostream.close(); + } + + /** + * get the root entry + * + * @return the root entry + */ + + public DirectoryNode getRoot() + { + if (_root == null) + { + _root = new DirectoryNode(_property_table.getRoot(), this, null); + } + return _root; + } + + /** + * open a document in the root entry's list of entries + * + * @param documentName the name of the document to be opened + * + * @return a newly opened DocumentInputStream + * + * @exception IOException if the document does not exist or the + * name is that of a DirectoryEntry + */ + + public DocumentInputStream createDocumentInputStream( + final String documentName) + throws IOException + { + return getRoot().createDocumentInputStream(documentName); + } + + /** + * add a new POIFSDocument + * + * @param document the POIFSDocument being added + */ + + void addDocument(final OPOIFSDocument document) + { + _documents.add(document); + _property_table.addProperty(document.getDocumentProperty()); + } + + /** + * add a new DirectoryProperty + * + * @param directory the DirectoryProperty being added + */ + + void addDirectory(final DirectoryProperty directory) + { + _property_table.addProperty(directory); + } + + /** + * remove an entry + * + * @param entry to be removed + */ + + void remove(EntryNode entry) + { + _property_table.removeProperty(entry.getProperty()); + if (entry.isDocumentEntry()) + { + _documents.remove((( DocumentNode ) entry).getDocument()); + } + } + + private void processProperties(final BlockList small_blocks, + final BlockList big_blocks, + final Iterator properties, + final DirectoryNode dir, + final int headerPropertiesStartAt) + throws IOException + { + while (properties.hasNext()) + { + Property property = properties.next(); + String name = property.getName(); + DirectoryNode parent = (dir == null) + ? (( DirectoryNode ) getRoot()) + : dir; + + if (property.isDirectory()) + { + DirectoryNode new_dir = + ( DirectoryNode ) parent.createDirectory(name); + + new_dir.setStorageClsid( property.getStorageClsid() ); + + processProperties( + small_blocks, big_blocks, + (( DirectoryProperty ) property).getChildren(), + new_dir, headerPropertiesStartAt); + } + else + { + int startBlock = property.getStartBlock(); + int size = property.getSize(); + OPOIFSDocument document = null; + + if (property.shouldUseSmallBlocks()) + { + document = + new OPOIFSDocument(name, + small_blocks.fetchBlocks(startBlock, headerPropertiesStartAt), + size); + } + else + { + document = + new OPOIFSDocument(name, + big_blocks.fetchBlocks(startBlock, headerPropertiesStartAt), + size); + } + parent.createDocument(document); + } + } + } + + /* ********** START begin implementation of POIFSViewable ********** */ + + /** + * Get an array of objects, some of which may implement + * POIFSViewable + * + * @return an array of Object; may not be null, but may be empty + */ + + public Object [] getViewableArray() + { + if (preferArray()) + { + return (( POIFSViewable ) getRoot()).getViewableArray(); + } + return new Object[ 0 ]; + } + + /** + * Get an Iterator of objects, some of which may implement + * POIFSViewable + * + * @return an Iterator; may not be null, but may have an empty + * back end store + */ + + public Iterator getViewableIterator() + { + if (!preferArray()) + { + return (( POIFSViewable ) getRoot()).getViewableIterator(); + } + return Collections.emptyList().iterator(); + } + + /** + * Give viewers a hint as to whether to call getViewableArray or + * getViewableIterator + * + * @return true if a viewer should call getViewableArray, false if + * a viewer should call getViewableIterator + */ + + public boolean preferArray() + { + return (( POIFSViewable ) getRoot()).preferArray(); + } + + /** + * Provides a short description of the object, to be used when a + * POIFSViewable object has not provided its contents. + * + * @return short description + */ + + public String getShortDescription() + { + return "POIFS FileSystem"; + } + + /** + * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes + */ + public int getBigBlockSize() { + return bigBlockSize.getBigBlockSize(); + } + /** + * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes + */ + public POIFSBigBlockSize getBigBlockSizeDetails() { + return bigBlockSize; + } + + /* ********** END begin implementation of POIFSViewable ********** */ +} // end public class OPOIFSFileSystem + diff --git a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java index 7169d91f9..5afb4eb8f 100644 --- a/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java +++ b/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java @@ -19,44 +19,22 @@ package org.apache.poi.poifs.filesystem; -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; -import java.io.PushbackInputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import org.apache.poi.poifs.common.POIFSBigBlockSize; -import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.dev.POIFSViewable; -import org.apache.poi.poifs.property.DirectoryProperty; -import org.apache.poi.poifs.property.Property; -import org.apache.poi.poifs.property.PropertyTable; -import org.apache.poi.poifs.storage.*; import org.apache.poi.util.CloseIgnoringInputStream; -import org.apache.poi.util.IOUtils; -import org.apache.poi.util.LongField; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; /** - * This is the main class of the POIFS system; it manages the entire - * life cycle of the filesystem. - * - * @author Marc Johnson (mjohnson at apache dot org) + * Transition class for the move from {@link POIFSFileSystem} to + * {@link OPOIFSFileSystem}, and from {@link NPOIFSFileSystem} to + * {@link POIFSFileSystem}. Currently, this is OPOIFS-powered */ public class POIFSFileSystem + extends NPOIFSFileSystem // TODO Temporary workaround during #56791 implements POIFSViewable { - private static final POILogger _logger = - POILogFactory.getLogger(POIFSFileSystem.class); - /** * Convenience method for clients that want to avoid the auto-close behaviour of the constructor. */ @@ -64,26 +42,12 @@ public class POIFSFileSystem return new CloseIgnoringInputStream(is); } - private PropertyTable _property_table; - private List _documents; - private DirectoryNode _root; - - /** - * What big block size the file uses. Most files - * use 512 bytes, but a few use 4096 - */ - private POIFSBigBlockSize bigBlockSize = - POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS; - /** * Constructor, intended for writing */ public POIFSFileSystem() { - HeaderBlock header_block = new HeaderBlock(bigBlockSize); - _property_table = new PropertyTable(header_block); - _documents = new ArrayList(); - _root = null; + super(); } /** @@ -118,76 +82,7 @@ public class POIFSFileSystem public POIFSFileSystem(InputStream stream) throws IOException { - this(); - boolean success = false; - - HeaderBlock header_block; - RawDataBlockList data_blocks; - try { - // read the header block from the stream - header_block = new HeaderBlock(stream); - bigBlockSize = header_block.getBigBlockSize(); - - // read the rest of the stream into blocks - data_blocks = new RawDataBlockList(stream, bigBlockSize); - success = true; - } finally { - closeInputStream(stream, success); - } - - - // set up the block allocation table (necessary for the - // data_blocks to be manageable - new BlockAllocationTableReader(header_block.getBigBlockSize(), - header_block.getBATCount(), - header_block.getBATArray(), - header_block.getXBATCount(), - header_block.getXBATIndex(), - data_blocks); - - // get property table from the document - PropertyTable properties = - new PropertyTable(header_block, data_blocks); - - // init documents - processProperties( - SmallBlockTableReader.getSmallDocumentBlocks( - bigBlockSize, data_blocks, properties.getRoot(), - header_block.getSBATStart() - ), - data_blocks, - properties.getRoot().getChildren(), - null, - header_block.getPropertyStart() - ); - - // For whatever reason CLSID of root is always 0. - getRoot().setStorageClsid(properties.getRoot().getStorageClsid()); - } - /** - * @param stream the stream to be closed - * @param success false if an exception is currently being thrown in the calling method - */ - private void closeInputStream(InputStream stream, boolean success) { - - if(stream.markSupported() && !(stream instanceof ByteArrayInputStream)) { - String msg = "POIFS is closing the supplied input stream of type (" - + stream.getClass().getName() + ") which supports mark/reset. " - + "This will be a problem for the caller if the stream will still be used. " - + "If that is the case the caller should wrap the input stream to avoid this close logic. " - + "This warning is only temporary and will not be present in future versions of POI."; - _logger.log(POILogger.WARN, msg); - } - try { - stream.close(); - } catch (IOException e) { - if(success) { - throw new RuntimeException(e); - } - // else not success? Try block did not complete normally - // just print stack trace and leave original ex to be thrown - e.printStackTrace(); - } + super(stream); } /** @@ -200,180 +95,14 @@ public class POIFSFileSystem * @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream */ public static boolean hasPOIFSHeader(InputStream inp) throws IOException { - // We want to peek at the first 8 bytes - inp.mark(8); - - byte[] header = new byte[8]; - IOUtils.readFully(inp, header); - LongField signature = new LongField(HeaderBlockConstants._signature_offset, header); - - // Wind back those 8 bytes - if(inp instanceof PushbackInputStream) { - PushbackInputStream pin = (PushbackInputStream)inp; - pin.unread(header); - } else { - inp.reset(); - } - - // Did it match the signature? - return (signature.get() == HeaderBlockConstants._signature); + return NPOIFSFileSystem.hasPOIFSHeader(inp); } - /** - * Create a new document to be added to the root directory - * - * @param stream the InputStream from which the document's data - * will be obtained - * @param name the name of the new POIFSDocument - * - * @return the new DocumentEntry - * - * @exception IOException on error creating the new POIFSDocument + * Checks if the supplied first 8 bytes of a stream / file + * has a POIFS (OLE2) header. */ - - public DocumentEntry createDocument(final InputStream stream, - final String name) - throws IOException - { - return getRoot().createDocument(name, stream); - } - - /** - * create a new DocumentEntry in the root entry; the data will be - * provided later - * - * @param name the name of the new DocumentEntry - * @param size the size of the new DocumentEntry - * @param writer the writer of the new DocumentEntry - * - * @return the new DocumentEntry - * - * @exception IOException - */ - - public DocumentEntry createDocument(final String name, final int size, - final POIFSWriterListener writer) - throws IOException - { - return getRoot().createDocument(name, size, writer); - } - - /** - * create a new DirectoryEntry in the root directory - * - * @param name the name of the new DirectoryEntry - * - * @return the new DirectoryEntry - * - * @exception IOException on name duplication - */ - - public DirectoryEntry createDirectory(final String name) - throws IOException - { - return getRoot().createDirectory(name); - } - - /** - * Write the filesystem out - * - * @param stream the OutputStream to which the filesystem will be - * written - * - * @exception IOException thrown on errors writing to the stream - */ - - public void writeFilesystem(final OutputStream stream) - throws IOException - { - - // get the property table ready - _property_table.preWrite(); - - // create the small block store, and the SBAT - SmallBlockTableWriter sbtw = - new SmallBlockTableWriter(bigBlockSize, _documents, _property_table.getRoot()); - - // create the block allocation table - BlockAllocationTableWriter bat = - new BlockAllocationTableWriter(bigBlockSize); - - // create a list of BATManaged objects: the documents plus the - // property table and the small block table - List bm_objects = new ArrayList(); - - bm_objects.addAll(_documents); - bm_objects.add(_property_table); - bm_objects.add(sbtw); - bm_objects.add(sbtw.getSBAT()); - - // walk the list, allocating space for each and assigning each - // a starting block number - Iterator iter = bm_objects.iterator(); - - while (iter.hasNext()) - { - BATManaged bmo = ( BATManaged ) iter.next(); - int block_count = bmo.countBlocks(); - - if (block_count != 0) - { - bmo.setStartBlock(bat.allocateSpace(block_count)); - } - else - { - - // Either the BATManaged object is empty or its data - // is composed of SmallBlocks; in either case, - // allocating space in the BAT is inappropriate - } - } - - // allocate space for the block allocation table and take its - // starting block - int batStartBlock = bat.createBlocks(); - - // get the extended block allocation table blocks - HeaderBlockWriter header_block_writer = new HeaderBlockWriter(bigBlockSize); - BATBlock[] xbat_blocks = - header_block_writer.setBATBlocks(bat.countBlocks(), - batStartBlock); - - // set the property table start block - header_block_writer.setPropertyStart(_property_table.getStartBlock()); - - // set the small block allocation table start block - header_block_writer.setSBATStart(sbtw.getSBAT().getStartBlock()); - - // set the small block allocation table block count - header_block_writer.setSBATBlockCount(sbtw.getSBATBlockCount()); - - // the header is now properly initialized. Make a list of - // writers (the header block, followed by the documents, the - // property table, the small block store, the small block - // allocation table, the block allocation table, and the - // extended block allocation table blocks) - List writers = new ArrayList(); - - writers.add(header_block_writer); - writers.addAll(_documents); - writers.add(_property_table); - writers.add(sbtw); - writers.add(sbtw.getSBAT()); - writers.add(bat); - for (int j = 0; j < xbat_blocks.length; j++) - { - writers.add(xbat_blocks[ j ]); - } - - // now, write everything out - iter = writers.iterator(); - while (iter.hasNext()) - { - BlockWritable writer = ( BlockWritable ) iter.next(); - - writer.writeBlocks(stream); - } + public static boolean hasPOIFSHeader(byte[] header8Bytes) { + return NPOIFSFileSystem.hasPOIFSHeader(header8Bytes); } /** @@ -388,216 +117,7 @@ public class POIFSFileSystem public static void main(String args[]) throws IOException { - if (args.length != 2) - { - System.err.println( - "two arguments required: input filename and output filename"); - System.exit(1); - } - FileInputStream istream = new FileInputStream(args[ 0 ]); - FileOutputStream ostream = new FileOutputStream(args[ 1 ]); - - new POIFSFileSystem(istream).writeFilesystem(ostream); - istream.close(); - ostream.close(); + OPOIFSFileSystem.main(args); } - - /** - * get the root entry - * - * @return the root entry - */ - - public DirectoryNode getRoot() - { - if (_root == null) - { - _root = new DirectoryNode(_property_table.getRoot(), this, null); - } - return _root; - } - - /** - * open a document in the root entry's list of entries - * - * @param documentName the name of the document to be opened - * - * @return a newly opened DocumentInputStream - * - * @exception IOException if the document does not exist or the - * name is that of a DirectoryEntry - */ - - public DocumentInputStream createDocumentInputStream( - final String documentName) - throws IOException - { - return getRoot().createDocumentInputStream(documentName); - } - - /** - * add a new POIFSDocument - * - * @param document the POIFSDocument being added - */ - - void addDocument(final POIFSDocument document) - { - _documents.add(document); - _property_table.addProperty(document.getDocumentProperty()); - } - - /** - * add a new DirectoryProperty - * - * @param directory the DirectoryProperty being added - */ - - void addDirectory(final DirectoryProperty directory) - { - _property_table.addProperty(directory); - } - - /** - * remove an entry - * - * @param entry to be removed - */ - - void remove(EntryNode entry) - { - _property_table.removeProperty(entry.getProperty()); - if (entry.isDocumentEntry()) - { - _documents.remove((( DocumentNode ) entry).getDocument()); - } - } - - private void processProperties(final BlockList small_blocks, - final BlockList big_blocks, - final Iterator properties, - final DirectoryNode dir, - final int headerPropertiesStartAt) - throws IOException - { - while (properties.hasNext()) - { - Property property = properties.next(); - String name = property.getName(); - DirectoryNode parent = (dir == null) - ? (( DirectoryNode ) getRoot()) - : dir; - - if (property.isDirectory()) - { - DirectoryNode new_dir = - ( DirectoryNode ) parent.createDirectory(name); - - new_dir.setStorageClsid( property.getStorageClsid() ); - - processProperties( - small_blocks, big_blocks, - (( DirectoryProperty ) property).getChildren(), - new_dir, headerPropertiesStartAt); - } - else - { - int startBlock = property.getStartBlock(); - int size = property.getSize(); - POIFSDocument document = null; - - if (property.shouldUseSmallBlocks()) - { - document = - new POIFSDocument(name, - small_blocks.fetchBlocks(startBlock, headerPropertiesStartAt), - size); - } - else - { - document = - new POIFSDocument(name, - big_blocks.fetchBlocks(startBlock, headerPropertiesStartAt), - size); - } - parent.createDocument(document); - } - } - } - - /* ********** START begin implementation of POIFSViewable ********** */ - - /** - * Get an array of objects, some of which may implement - * POIFSViewable - * - * @return an array of Object; may not be null, but may be empty - */ - - public Object [] getViewableArray() - { - if (preferArray()) - { - return (( POIFSViewable ) getRoot()).getViewableArray(); - } - return new Object[ 0 ]; - } - - /** - * Get an Iterator of objects, some of which may implement - * POIFSViewable - * - * @return an Iterator; may not be null, but may have an empty - * back end store - */ - - public Iterator getViewableIterator() - { - if (!preferArray()) - { - return (( POIFSViewable ) getRoot()).getViewableIterator(); - } - return Collections.emptyList().iterator(); - } - - /** - * Give viewers a hint as to whether to call getViewableArray or - * getViewableIterator - * - * @return true if a viewer should call getViewableArray, false if - * a viewer should call getViewableIterator - */ - - public boolean preferArray() - { - return (( POIFSViewable ) getRoot()).preferArray(); - } - - /** - * Provides a short description of the object, to be used when a - * POIFSViewable object has not provided its contents. - * - * @return short description - */ - - public String getShortDescription() - { - return "POIFS FileSystem"; - } - - /** - * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes - */ - public int getBigBlockSize() { - return bigBlockSize.getBigBlockSize(); - } - /** - * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes - */ - public POIFSBigBlockSize getBigBlockSizeDetails() { - return bigBlockSize; - } - - /* ********** END begin implementation of POIFSViewable ********** */ -} // end public class POIFSFileSystem +} diff --git a/src/java/org/apache/poi/poifs/property/DirectoryProperty.java b/src/java/org/apache/poi/poifs/property/DirectoryProperty.java index a73221af2..d86e73ada 100644 --- a/src/java/org/apache/poi/poifs/property/DirectoryProperty.java +++ b/src/java/org/apache/poi/poifs/property/DirectoryProperty.java @@ -28,10 +28,8 @@ import java.util.Set; /** * Directory property - * - * @author Marc Johnson (mjohnson at apache dot org) */ -public class DirectoryProperty extends Property implements Parent { // TODO - fix instantiable superclass +public class DirectoryProperty extends Property implements Parent, Iterable { // TODO - fix instantiable superclass /** List of Property instances */ private List _children; @@ -241,6 +239,13 @@ public class DirectoryProperty extends Property implements Parent { // TODO - fi { return _children.iterator(); } + /** + * Get an iterator over the children of this Parent, alias for + * {@link #getChildren()} which supports foreach use + */ + public Iterator iterator() { + return getChildren(); + } /** * Add a new child to the collection of children diff --git a/src/java/org/apache/poi/poifs/property/DocumentProperty.java b/src/java/org/apache/poi/poifs/property/DocumentProperty.java index 67c8b0307..3ba3c0889 100644 --- a/src/java/org/apache/poi/poifs/property/DocumentProperty.java +++ b/src/java/org/apache/poi/poifs/property/DocumentProperty.java @@ -19,12 +19,10 @@ package org.apache.poi.poifs.property; -import org.apache.poi.poifs.filesystem.POIFSDocument; +import org.apache.poi.poifs.filesystem.OPOIFSDocument; /** * Trivial extension of Property for POIFSDocuments - * - * @author Marc Johnson (mjohnson at apache dot org) */ public class DocumentProperty @@ -32,7 +30,7 @@ public class DocumentProperty { // the POIFSDocument this property is associated with - private POIFSDocument _document; + private OPOIFSDocument _document; /** * Constructor @@ -72,7 +70,7 @@ public class DocumentProperty * @param doc the associated POIFSDocument */ - public void setDocument(POIFSDocument doc) + public void setDocument(OPOIFSDocument doc) { _document = doc; } @@ -83,7 +81,7 @@ public class DocumentProperty * @return the associated document */ - public POIFSDocument getDocument() + public OPOIFSDocument getDocument() { return _document; } diff --git a/src/java/org/apache/poi/poifs/property/PropertyTable.java b/src/java/org/apache/poi/poifs/property/PropertyTable.java index 45a973415..75ca4a03b 100644 --- a/src/java/org/apache/poi/poifs/property/PropertyTable.java +++ b/src/java/org/apache/poi/poifs/property/PropertyTable.java @@ -21,14 +21,13 @@ import java.io.IOException; import java.io.OutputStream; import org.apache.poi.poifs.common.POIFSBigBlockSize; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.storage.BlockWritable; import org.apache.poi.poifs.storage.HeaderBlock; import org.apache.poi.poifs.storage.PropertyBlock; import org.apache.poi.poifs.storage.RawDataBlockList; /** - * This class embodies the Property Table for the {@link POIFSFileSystem}; + * This class embodies the Property Table for the {@link org.apache.poi.poifs.filesystem.POIFSFileSystem}; * this is basically the directory for all of the documents in the * filesystem. * diff --git a/src/java/org/apache/poi/poifs/property/PropertyTableBase.java b/src/java/org/apache/poi/poifs/property/PropertyTableBase.java index b3690c5c2..477cf036d 100644 --- a/src/java/org/apache/poi/poifs/property/PropertyTableBase.java +++ b/src/java/org/apache/poi/poifs/property/PropertyTableBase.java @@ -111,6 +111,11 @@ public abstract class PropertyTableBase implements BATManaged { while (!children.empty()) { Property property = children.pop(); + if (property == null) + { + // unknown / unsupported / corrupted property, skip + continue; + } root.addChild(property); if (property.isDirectory()) diff --git a/src/java/org/apache/poi/poifs/property/RootProperty.java b/src/java/org/apache/poi/poifs/property/RootProperty.java index b934a2601..5a8f3d52e 100644 --- a/src/java/org/apache/poi/poifs/property/RootProperty.java +++ b/src/java/org/apache/poi/poifs/property/RootProperty.java @@ -22,8 +22,6 @@ import org.apache.poi.poifs.storage.SmallDocumentBlock; /** * Root property - * - * @author Marc Johnson (mjohnson at apache dot org) */ public final class RootProperty extends DirectoryProperty { private static final String NAME = "Root Entry"; diff --git a/src/java/org/apache/poi/poifs/storage/BATBlock.java b/src/java/org/apache/poi/poifs/storage/BATBlock.java index 8712e65f6..53099644a 100644 --- a/src/java/org/apache/poi/poifs/storage/BATBlock.java +++ b/src/java/org/apache/poi/poifs/storage/BATBlock.java @@ -30,8 +30,6 @@ import org.apache.poi.util.LittleEndian; /** * A block of block allocation table entries. BATBlocks are created * only through a static factory method: createBATBlocks. - * - * @author Marc Johnson (mjohnson at apache dot org) */ public final class BATBlock extends BigBlock { /** @@ -301,6 +299,21 @@ public final class BATBlock extends BigBlock { public boolean hasFreeSectors() { return _has_free_sectors; } + /** + * How many sectors in this block are taken? + * Note that calling {@link #hasFreeSectors()} is much quicker + */ + public int getUsedSectors(boolean isAnXBAT) { + int usedSectors = 0; + int toCheck = _values.length; + if (isAnXBAT) toCheck--; // Last is a chain location + for(int k=0; k= _values.length) { diff --git a/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java b/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java index 8b6efd36e..2f9528318 100644 --- a/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java +++ b/src/java/org/apache/poi/poifs/storage/SmallBlockTableReader.java @@ -25,13 +25,66 @@ import org.apache.poi.poifs.property.RootProperty; /** * This class implements reading the small document block list from an * existing file - * - * @author Marc Johnson (mjohnson at apache dot org) */ public final class SmallBlockTableReader { + private static BlockList prepareSmallDocumentBlocks( + final POIFSBigBlockSize bigBlockSize, + final RawDataBlockList blockList, final RootProperty root, + final int sbatStart) + throws IOException + { + // Fetch the blocks which hold the Small Blocks stream + ListManagedBlock [] smallBlockBlocks = + blockList.fetchBlocks(root.getStartBlock(), -1); + + // Turn that into a list + BlockList list =new SmallDocumentBlockList( + SmallDocumentBlock.extract(bigBlockSize, smallBlockBlocks)); + + return list; + } + private static BlockAllocationTableReader prepareReader( + final POIFSBigBlockSize bigBlockSize, + final RawDataBlockList blockList, final BlockList list, + final RootProperty root, final int sbatStart) + throws IOException + { + // Process the SBAT and blocks + return new BlockAllocationTableReader(bigBlockSize, + blockList.fetchBlocks(sbatStart, -1), + list); + } + + /** + * Fetch the small document block reader from an existing file, normally + * needed for debugging and low level dumping. You should typically call + * {@link #getSmallDocumentBlocks(POIFSBigBlockSize, RawDataBlockList, RootProperty, int)} + * instead. + * + * @param blockList the raw data from which the small block table + * will be extracted + * @param root the root property (which contains the start block + * and small block table size) + * @param sbatStart the start block of the SBAT + * + * @return the small document block reader + * + * @exception IOException + */ + public static BlockAllocationTableReader _getSmallDocumentBlockReader( + final POIFSBigBlockSize bigBlockSize, + final RawDataBlockList blockList, final RootProperty root, + final int sbatStart) + throws IOException + { + BlockList list = prepareSmallDocumentBlocks( + bigBlockSize, blockList, root, sbatStart); + return prepareReader( + bigBlockSize, blockList, list, root, sbatStart); + } /** - * fetch the small document block list from an existing file + * Fetch the small document block list from an existing file * * @param blockList the raw data from which the small block table * will be extracted @@ -49,18 +102,9 @@ public final class SmallBlockTableReader { final int sbatStart) throws IOException { - // Fetch the blocks which hold the Small Blocks stream - ListManagedBlock [] smallBlockBlocks = - blockList.fetchBlocks(root.getStartBlock(), -1); - - // Turn that into a list - BlockList list =new SmallDocumentBlockList( - SmallDocumentBlock.extract(bigBlockSize, smallBlockBlocks)); - - // Process - new BlockAllocationTableReader(bigBlockSize, - blockList.fetchBlocks(sbatStart, -1), - list); + BlockList list = prepareSmallDocumentBlocks( + bigBlockSize, blockList, root, sbatStart); + prepareReader(bigBlockSize, blockList, list, root, sbatStart); return list; } } diff --git a/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java b/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java index 2db7bf4c7..9c98bb459 100644 --- a/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java +++ b/src/java/org/apache/poi/poifs/storage/SmallBlockTableWriter.java @@ -22,7 +22,7 @@ package org.apache.poi.poifs.storage; import org.apache.poi.poifs.common.POIFSBigBlockSize; import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.filesystem.BATManaged; -import org.apache.poi.poifs.filesystem.POIFSDocument; +import org.apache.poi.poifs.filesystem.OPOIFSDocument; import org.apache.poi.poifs.property.RootProperty; import java.util.*; @@ -40,7 +40,7 @@ public class SmallBlockTableWriter implements BlockWritable, BATManaged { private BlockAllocationTableWriter _sbat; - private List _small_blocks; + private List _small_blocks; private int _big_block_count; private RootProperty _root; @@ -50,20 +50,17 @@ public class SmallBlockTableWriter * @param documents a List of POIFSDocument instances * @param root the Filesystem's root property */ - public SmallBlockTableWriter(final POIFSBigBlockSize bigBlockSize, - final List documents, + final List documents, final RootProperty root) { _sbat = new BlockAllocationTableWriter(bigBlockSize); - _small_blocks = new ArrayList(); + _small_blocks = new ArrayList(); _root = root; - Iterator iter = documents.iterator(); - while (iter.hasNext()) + for (OPOIFSDocument doc : documents) { - POIFSDocument doc = ( POIFSDocument ) iter.next(); - BlockWritable[] blocks = doc.getSmallBlocks(); + SmallDocumentBlock[] blocks = doc.getSmallBlocks(); if (blocks.length != 0) { @@ -143,11 +140,8 @@ public class SmallBlockTableWriter public void writeBlocks(final OutputStream stream) throws IOException { - Iterator iter = _small_blocks.iterator(); - - while (iter.hasNext()) - { - (( BlockWritable ) iter.next()).writeBlocks(stream); + for (BlockWritable block : _small_blocks) { + block.writeBlocks(stream); } } diff --git a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java index 8c726caa0..d09bf9ecf 100644 --- a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java +++ b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlock.java @@ -29,8 +29,6 @@ import org.apache.poi.poifs.common.POIFSBigBlockSize; /** * Storage for documents that are too small to use regular * DocumentBlocks for their data - * - * @author Marc Johnson (mjohnson at apache dot org) */ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock { private static final int BLOCK_SHIFT = 6; @@ -49,7 +47,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock System.arraycopy(data, index * _block_size, _data, 0, _block_size); } - private SmallDocumentBlock(final POIFSBigBlockSize bigBlockSize) + protected SmallDocumentBlock(final POIFSBigBlockSize bigBlockSize) { _bigBlockSize = bigBlockSize; _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize); @@ -110,7 +108,7 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock * * @return number of big blocks the list encompasses */ - public static int fill(POIFSBigBlockSize bigBlockSize, List blocks) + public static int fill(POIFSBigBlockSize bigBlockSize, List blocks) { int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize); @@ -168,12 +166,12 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock * * @return a List of SmallDocumentBlock's extracted from the input */ - public static List extract(POIFSBigBlockSize bigBlockSize, ListManagedBlock [] blocks) + public static List extract(POIFSBigBlockSize bigBlockSize, ListManagedBlock [] blocks) throws IOException { int _blocks_per_big_block = getBlocksPerBigBlock(bigBlockSize); - List sdbs = new ArrayList(); + List sdbs = new ArrayList(); for (int j = 0; j < blocks.length; j++) { @@ -204,6 +202,11 @@ public final class SmallDocumentBlock implements BlockWritable, ListManagedBlock { return size * _block_size; } + + protected int getSmallBlocksPerBigBlock() + { + return _blocks_per_big_block; + } private static SmallDocumentBlock makeEmptySmallDocumentBlock(POIFSBigBlockSize bigBlockSize) { diff --git a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java index a510f8e8f..cc6bb7c17 100644 --- a/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java +++ b/src/java/org/apache/poi/poifs/storage/SmallDocumentBlockList.java @@ -23,24 +23,19 @@ import java.util.*; /** * A list of SmallDocumentBlocks instances, and methods to manage the list - * - * @author Marc Johnson (mjohnson at apache dot org) */ - public class SmallDocumentBlockList extends BlockListImpl { - /** * Constructor SmallDocumentBlockList * * @param blocks a list of SmallDocumentBlock instances */ - public SmallDocumentBlockList(final List blocks) + public SmallDocumentBlockList(final List blocks) { - setBlocks(( SmallDocumentBlock [] ) blocks - .toArray(new SmallDocumentBlock[ blocks.size() ])); + setBlocks(blocks.toArray(new SmallDocumentBlock[blocks.size()])); } -} // end public class SmallDocumentBlockList +} diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawAutoShape.java b/src/java/org/apache/poi/sl/draw/DrawAutoShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawAutoShape.java rename to src/java/org/apache/poi/sl/draw/DrawAutoShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawBackground.java b/src/java/org/apache/poi/sl/draw/DrawBackground.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawBackground.java rename to src/java/org/apache/poi/sl/draw/DrawBackground.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawConnectorShape.java b/src/java/org/apache/poi/sl/draw/DrawConnectorShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawConnectorShape.java rename to src/java/org/apache/poi/sl/draw/DrawConnectorShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java b/src/java/org/apache/poi/sl/draw/DrawFactory.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java rename to src/java/org/apache/poi/sl/draw/DrawFactory.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawFontManager.java b/src/java/org/apache/poi/sl/draw/DrawFontManager.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawFontManager.java rename to src/java/org/apache/poi/sl/draw/DrawFontManager.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawFreeformShape.java b/src/java/org/apache/poi/sl/draw/DrawFreeformShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawFreeformShape.java rename to src/java/org/apache/poi/sl/draw/DrawFreeformShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawGroupShape.java b/src/java/org/apache/poi/sl/draw/DrawGroupShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawGroupShape.java rename to src/java/org/apache/poi/sl/draw/DrawGroupShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawMasterSheet.java b/src/java/org/apache/poi/sl/draw/DrawMasterSheet.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawMasterSheet.java rename to src/java/org/apache/poi/sl/draw/DrawMasterSheet.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawPaint.java b/src/java/org/apache/poi/sl/draw/DrawPaint.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawPaint.java rename to src/java/org/apache/poi/sl/draw/DrawPaint.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawPictureShape.java b/src/java/org/apache/poi/sl/draw/DrawPictureShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawPictureShape.java rename to src/java/org/apache/poi/sl/draw/DrawPictureShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawShape.java b/src/java/org/apache/poi/sl/draw/DrawShape.java similarity index 96% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawShape.java rename to src/java/org/apache/poi/sl/draw/DrawShape.java index c2c9b5f68..13ef4292a 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawShape.java @@ -21,7 +21,6 @@ import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; -import org.apache.poi.hslf.usermodel.HSLFShape; import org.apache.poi.sl.usermodel.PlaceableShape; import org.apache.poi.sl.usermodel.Shape; @@ -73,7 +72,7 @@ public class DrawShape implements Drawable { // and later on, turn it around again to compare it with its original size ... AffineTransform txs; - if (ps instanceof HSLFShape) { + if (ps.getClass().getCanonicalName().toLowerCase().contains("hslf")) { txs = new AffineTransform(tx); } else { // this handling is only based on try and error ... not sure why xslf is handled differently. diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSheet.java b/src/java/org/apache/poi/sl/draw/DrawSheet.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawSheet.java rename to src/java/org/apache/poi/sl/draw/DrawSheet.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSimpleShape.java b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawSimpleShape.java rename to src/java/org/apache/poi/sl/draw/DrawSimpleShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSlide.java b/src/java/org/apache/poi/sl/draw/DrawSlide.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawSlide.java rename to src/java/org/apache/poi/sl/draw/DrawSlide.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTableShape.java b/src/java/org/apache/poi/sl/draw/DrawTableShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTableShape.java rename to src/java/org/apache/poi/sl/draw/DrawTableShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextBox.java b/src/java/org/apache/poi/sl/draw/DrawTextBox.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTextBox.java rename to src/java/org/apache/poi/sl/draw/DrawTextBox.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextFragment.java b/src/java/org/apache/poi/sl/draw/DrawTextFragment.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTextFragment.java rename to src/java/org/apache/poi/sl/draw/DrawTextFragment.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextParagraph.java b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTextParagraph.java rename to src/java/org/apache/poi/sl/draw/DrawTextParagraph.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java b/src/java/org/apache/poi/sl/draw/DrawTextShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java rename to src/java/org/apache/poi/sl/draw/DrawTextShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/Drawable.java b/src/java/org/apache/poi/sl/draw/Drawable.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/Drawable.java rename to src/java/org/apache/poi/sl/draw/Drawable.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/ImageRenderer.java b/src/java/org/apache/poi/sl/draw/ImageRenderer.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/ImageRenderer.java rename to src/java/org/apache/poi/sl/draw/ImageRenderer.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/PathGradientPaint.java b/src/java/org/apache/poi/sl/draw/PathGradientPaint.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/PathGradientPaint.java rename to src/java/org/apache/poi/sl/draw/PathGradientPaint.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java b/src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java index 32ee2a03b..d7fc0ae07 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTAdjPoint2D.java @@ -45,9 +45,9 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_AdjPoint2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTAdjPoint2D { - @XmlAttribute(required = true) + @XmlAttribute(name = "x", required = true) protected String x; - @XmlAttribute(required = true) + @XmlAttribute(name = "y", required = true) protected String y; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java b/src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java similarity index 96% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java rename to src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java index c5ef7860b..d684cccb7 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTAdjustHandleList.java @@ -53,8 +53,8 @@ import javax.xml.bind.annotation.XmlType; public class CTAdjustHandleList { @XmlElements({ - @XmlElement(name = "ahPolar", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPolarAdjustHandle.class), - @XmlElement(name = "ahXY", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTXYAdjustHandle.class) + @XmlElement(name = "ahXY", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTXYAdjustHandle.class), + @XmlElement(name = "ahPolar", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPolarAdjustHandle.class) }) protected List ahXYOrAhPolar; @@ -76,8 +76,8 @@ public class CTAdjustHandleList { * *

    * Objects of the following type(s) are allowed in the list - * {@link CTPolarAdjustHandle } * {@link CTXYAdjustHandle } + * {@link CTPolarAdjustHandle } * * */ diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAngle.java b/src/java/org/apache/poi/sl/draw/binding/CTAngle.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAngle.java rename to src/java/org/apache/poi/sl/draw/binding/CTAngle.java index 2e39602da..2da2373e2 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTAngle.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTAngle.java @@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_Angle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTAngle { - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) protected int val; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColor.java b/src/java/org/apache/poi/sl/draw/binding/CTColor.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColor.java rename to src/java/org/apache/poi/sl/draw/binding/CTColor.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColorMRU.java b/src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java similarity index 97% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColorMRU.java rename to src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java index fb3e2cc61..8ec68ba08 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTColorMRU.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTColorMRU.java @@ -52,12 +52,12 @@ import javax.xml.bind.annotation.XmlType; public class CTColorMRU { @XmlElements({ - @XmlElement(name = "hslClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTHslColor.class), - @XmlElement(name = "srgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSRgbColor.class), - @XmlElement(name = "schemeClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSchemeColor.class), @XmlElement(name = "scrgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTScRgbColor.class), - @XmlElement(name = "prstClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPresetColor.class), - @XmlElement(name = "sysClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSystemColor.class) + @XmlElement(name = "srgbClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSRgbColor.class), + @XmlElement(name = "hslClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTHslColor.class), + @XmlElement(name = "sysClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSystemColor.class), + @XmlElement(name = "schemeClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTSchemeColor.class), + @XmlElement(name = "prstClr", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPresetColor.class) }) protected List egColorChoice; @@ -79,12 +79,12 @@ public class CTColorMRU { * *

    * Objects of the following type(s) are allowed in the list - * {@link CTHslColor } - * {@link CTSRgbColor } - * {@link CTSchemeColor } * {@link CTScRgbColor } - * {@link CTPresetColor } + * {@link CTSRgbColor } + * {@link CTHslColor } * {@link CTSystemColor } + * {@link CTSchemeColor } + * {@link CTPresetColor } * * */ diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTComplementTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTComplementTransform.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTComplementTransform.java rename to src/java/org/apache/poi/sl/draw/binding/CTComplementTransform.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnection.java b/src/java/org/apache/poi/sl/draw/binding/CTConnection.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnection.java rename to src/java/org/apache/poi/sl/draw/binding/CTConnection.java index 4af3fac71..f5d5e1726 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnection.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTConnection.java @@ -46,9 +46,9 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_Connection", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTConnection { - @XmlAttribute(required = true) + @XmlAttribute(name = "id", required = true) protected long id; - @XmlAttribute(required = true) + @XmlAttribute(name = "idx", required = true) @XmlSchemaType(name = "unsignedInt") protected long idx; diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSite.java b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java similarity index 95% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSite.java rename to src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java index 7ec62972d..eae59a0f0 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSite.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSite.java @@ -52,7 +52,7 @@ public class CTConnectionSite { @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) protected CTAdjPoint2D pos; - @XmlAttribute(required = true) + @XmlAttribute(name = "ang", required = true) protected String ang; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java b/src/java/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java rename to src/java/org/apache/poi/sl/draw/binding/CTConnectionSiteList.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java b/src/java/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTCustomGeometry2D.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java b/src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java similarity index 91% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java rename to src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java index 94d44ece2..8787125f4 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTEmbeddedWAVAudioFile.java @@ -46,11 +46,11 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_EmbeddedWAVAudioFile", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTEmbeddedWAVAudioFile { - @XmlAttribute(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", required = true) + @XmlAttribute(name = "embed", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships", required = true) protected String embed; - @XmlAttribute + @XmlAttribute(name = "name") protected String name; - @XmlAttribute + @XmlAttribute(name = "builtIn") protected Boolean builtIn; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTFixedPercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTFixedPercentage.java rename to src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java index 92f41aee8..d1ed283f5 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTFixedPercentage.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTFixedPercentage.java @@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_FixedPercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTFixedPercentage { - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) protected int val; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGammaTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTGammaTransform.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGammaTransform.java rename to src/java/org/apache/poi/sl/draw/binding/CTGammaTransform.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuide.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuide.java rename to src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java index 3df22093c..5622e4c28 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuide.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuide.java @@ -47,10 +47,10 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlType(name = "CT_GeomGuide", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTGeomGuide { - @XmlAttribute(required = true) + @XmlAttribute(name = "name", required = true) @XmlJavaTypeAdapter(CollapsedStringAdapter.class) protected String name; - @XmlAttribute(required = true) + @XmlAttribute(name = "fmla", required = true) protected String fmla; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuideList.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomGuideList.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomGuideList.java rename to src/java/org/apache/poi/sl/draw/binding/CTGeomGuideList.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomRect.java b/src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java similarity index 92% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomRect.java rename to src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java index b1368be29..3198f0410 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGeomRect.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGeomRect.java @@ -47,13 +47,13 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_GeomRect", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTGeomRect { - @XmlAttribute(required = true) + @XmlAttribute(name = "l", required = true) protected String l; - @XmlAttribute(required = true) + @XmlAttribute(name = "t", required = true) protected String t; - @XmlAttribute(required = true) + @XmlAttribute(name = "r", required = true) protected String r; - @XmlAttribute(required = true) + @XmlAttribute(name = "b", required = true) protected String b; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java rename to src/java/org/apache/poi/sl/draw/binding/CTGrayscaleTransform.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java b/src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java index 6508613b1..f06e1d8f9 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTGroupTransform2D.java @@ -66,11 +66,11 @@ public class CTGroupTransform2D { protected CTPoint2D chOff; @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") protected CTPositiveSize2D chExt; - @XmlAttribute + @XmlAttribute(name = "rot") protected Integer rot; - @XmlAttribute + @XmlAttribute(name = "flipH") protected Boolean flipH; - @XmlAttribute + @XmlAttribute(name = "flipV") protected Boolean flipV; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHslColor.java b/src/java/org/apache/poi/sl/draw/binding/CTHslColor.java similarity index 90% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHslColor.java rename to src/java/org/apache/poi/sl/draw/binding/CTHslColor.java index c5bca5aec..376d423ee 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHslColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTHslColor.java @@ -57,41 +57,41 @@ import javax.xml.bind.annotation.XmlType; public class CTHslColor { @XmlElementRefs({ - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false) }) protected List> egColorTransform; - @XmlAttribute(required = true) + @XmlAttribute(name = "hue", required = true) protected int hue; - @XmlAttribute(required = true) + @XmlAttribute(name = "sat", required = true) protected int sat; - @XmlAttribute(required = true) + @XmlAttribute(name = "lum", required = true) protected int lum; /** @@ -112,34 +112,34 @@ public class CTHslColor { * *

    * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} * * */ diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHyperlink.java b/src/java/org/apache/poi/sl/draw/binding/CTHyperlink.java similarity index 92% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHyperlink.java rename to src/java/org/apache/poi/sl/draw/binding/CTHyperlink.java index 03e486af5..0c89f392a 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTHyperlink.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTHyperlink.java @@ -63,21 +63,21 @@ public class CTHyperlink { protected CTEmbeddedWAVAudioFile snd; @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") protected CTOfficeArtExtensionList extLst; - @XmlAttribute(namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships") + @XmlAttribute(name = "id", namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships") protected String id; - @XmlAttribute + @XmlAttribute(name = "invalidUrl") protected String invalidUrl; - @XmlAttribute + @XmlAttribute(name = "action") protected String action; - @XmlAttribute + @XmlAttribute(name = "tgtFrame") protected String tgtFrame; - @XmlAttribute + @XmlAttribute(name = "tooltip") protected String tooltip; - @XmlAttribute + @XmlAttribute(name = "history") protected Boolean history; - @XmlAttribute + @XmlAttribute(name = "highlightClick") protected Boolean highlightClick; - @XmlAttribute + @XmlAttribute(name = "endSnd") protected Boolean endSnd; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTInverseGammaTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTInverseGammaTransform.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTInverseGammaTransform.java rename to src/java/org/apache/poi/sl/draw/binding/CTInverseGammaTransform.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTInverseTransform.java b/src/java/org/apache/poi/sl/draw/binding/CTInverseTransform.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTInverseTransform.java rename to src/java/org/apache/poi/sl/draw/binding/CTInverseTransform.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java b/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java similarity index 95% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java rename to src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java index adb928fbe..ec864d3b5 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtension.java @@ -56,7 +56,7 @@ public class CTOfficeArtExtension { @XmlAnyElement(lax = true) protected Object any; - @XmlAttribute + @XmlAttribute(name = "uri") @XmlJavaTypeAdapter(CollapsedStringAdapter.class) @XmlSchemaType(name = "token") protected String uri; @@ -66,8 +66,8 @@ public class CTOfficeArtExtension { * * @return * possible object is - * {@link Element } * {@link Object } + * {@link Element } * */ public Object getAny() { @@ -79,8 +79,8 @@ public class CTOfficeArtExtension { * * @param value * allowed object is - * {@link Element } * {@link Object } + * {@link Element } * */ public void setAny(Object value) { diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTOfficeArtExtensionList.java b/src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtensionList.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTOfficeArtExtensionList.java rename to src/java/org/apache/poi/sl/draw/binding/CTOfficeArtExtensionList.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2D.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2D.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTPath2D.java index 84b919843..529481296 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2D.java @@ -63,23 +63,23 @@ import javax.xml.bind.annotation.XmlType; public class CTPath2D { @XmlElements({ + @XmlElement(name = "close", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DClose.class), @XmlElement(name = "moveTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DMoveTo.class), - @XmlElement(name = "quadBezTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DQuadBezierTo.class), - @XmlElement(name = "cubicBezTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DCubicBezierTo.class), - @XmlElement(name = "arcTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DArcTo.class), @XmlElement(name = "lnTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DLineTo.class), - @XmlElement(name = "close", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DClose.class) + @XmlElement(name = "arcTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DArcTo.class), + @XmlElement(name = "quadBezTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DQuadBezierTo.class), + @XmlElement(name = "cubicBezTo", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = CTPath2DCubicBezierTo.class) }) protected List closeOrMoveToOrLnTo; - @XmlAttribute + @XmlAttribute(name = "w") protected Long w; - @XmlAttribute + @XmlAttribute(name = "h") protected Long h; - @XmlAttribute + @XmlAttribute(name = "fill") protected STPathFillMode fill; - @XmlAttribute + @XmlAttribute(name = "stroke") protected Boolean stroke; - @XmlAttribute + @XmlAttribute(name = "extrusionOk") protected Boolean extrusionOk; /** @@ -100,12 +100,12 @@ public class CTPath2D { * *

    * Objects of the following type(s) are allowed in the list + * {@link CTPath2DClose } * {@link CTPath2DMoveTo } + * {@link CTPath2DLineTo } + * {@link CTPath2DArcTo } * {@link CTPath2DQuadBezierTo } * {@link CTPath2DCubicBezierTo } - * {@link CTPath2DArcTo } - * {@link CTPath2DLineTo } - * {@link CTPath2DClose } * * */ diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java rename to src/java/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java index a4c325aa1..5464ee4d1 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPath2DArcTo.java @@ -51,9 +51,9 @@ public class CTPath2DArcTo { protected String wr; @XmlAttribute(name = "hR", required = true) protected String hr; - @XmlAttribute(required = true) + @XmlAttribute(name = "stAng", required = true) protected String stAng; - @XmlAttribute(required = true) + @XmlAttribute(name = "swAng", required = true) protected String swAng; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DClose.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DClose.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DClose.java rename to src/java/org/apache/poi/sl/draw/binding/CTPath2DClose.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DCubicBezierTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DCubicBezierTo.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DCubicBezierTo.java rename to src/java/org/apache/poi/sl/draw/binding/CTPath2DCubicBezierTo.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DLineTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DLineTo.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DLineTo.java rename to src/java/org/apache/poi/sl/draw/binding/CTPath2DLineTo.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DList.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DList.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DList.java rename to src/java/org/apache/poi/sl/draw/binding/CTPath2DList.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DMoveTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DMoveTo.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DMoveTo.java rename to src/java/org/apache/poi/sl/draw/binding/CTPath2DMoveTo.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DQuadBezierTo.java b/src/java/org/apache/poi/sl/draw/binding/CTPath2DQuadBezierTo.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPath2DQuadBezierTo.java rename to src/java/org/apache/poi/sl/draw/binding/CTPath2DQuadBezierTo.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTPercentage.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPercentage.java rename to src/java/org/apache/poi/sl/draw/binding/CTPercentage.java index 7ca8c1fec..e1a74b53e 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPercentage.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPercentage.java @@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_Percentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTPercentage { - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) protected int val; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPoint2D.java b/src/java/org/apache/poi/sl/draw/binding/CTPoint2D.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPoint2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTPoint2D.java index ae8798603..06cbfbc7a 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPoint2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPoint2D.java @@ -45,9 +45,9 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_Point2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTPoint2D { - @XmlAttribute(required = true) + @XmlAttribute(name = "x", required = true) protected long x; - @XmlAttribute(required = true) + @XmlAttribute(name = "y", required = true) protected long y; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPoint3D.java b/src/java/org/apache/poi/sl/draw/binding/CTPoint3D.java similarity index 92% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPoint3D.java rename to src/java/org/apache/poi/sl/draw/binding/CTPoint3D.java index e14c6ba4f..3cbeb670f 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPoint3D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPoint3D.java @@ -46,11 +46,11 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_Point3D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTPoint3D { - @XmlAttribute(required = true) + @XmlAttribute(name = "x", required = true) protected long x; - @XmlAttribute(required = true) + @XmlAttribute(name = "y", required = true) protected long y; - @XmlAttribute(required = true) + @XmlAttribute(name = "z", required = true) protected long z; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java b/src/java/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java rename to src/java/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java index 9547ca988..646dad5b5 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPolarAdjustHandle.java @@ -59,19 +59,19 @@ public class CTPolarAdjustHandle { @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) protected CTAdjPoint2D pos; - @XmlAttribute + @XmlAttribute(name = "gdRefR") @XmlJavaTypeAdapter(CollapsedStringAdapter.class) protected String gdRefR; - @XmlAttribute + @XmlAttribute(name = "minR") protected String minR; - @XmlAttribute + @XmlAttribute(name = "maxR") protected String maxR; - @XmlAttribute + @XmlAttribute(name = "gdRefAng") @XmlJavaTypeAdapter(CollapsedStringAdapter.class) protected String gdRefAng; - @XmlAttribute + @XmlAttribute(name = "minAng") protected String minAng; - @XmlAttribute + @XmlAttribute(name = "maxAng") protected String maxAng; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java b/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java rename to src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java index 94348d9bf..962db9513 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedAngle.java @@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_PositiveFixedAngle", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTPositiveFixedAngle { - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) protected int val; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java similarity index 95% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java rename to src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java index de659159e..001f01adc 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPositiveFixedPercentage.java @@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_PositiveFixedPercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTPositiveFixedPercentage { - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) protected int val; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositivePercentage.java b/src/java/org/apache/poi/sl/draw/binding/CTPositivePercentage.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositivePercentage.java rename to src/java/org/apache/poi/sl/draw/binding/CTPositivePercentage.java index 7b377e144..8fc61f301 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositivePercentage.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPositivePercentage.java @@ -44,7 +44,7 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_PositivePercentage", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTPositivePercentage { - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) protected int val; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java b/src/java/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java index 210fd925a..c8d76e6e5 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPositiveSize2D.java @@ -45,9 +45,9 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_PositiveSize2D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTPositiveSize2D { - @XmlAttribute(required = true) + @XmlAttribute(name = "cx", required = true) protected long cx; - @XmlAttribute(required = true) + @XmlAttribute(name = "cy", required = true) protected long cy; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetColor.java b/src/java/org/apache/poi/sl/draw/binding/CTPresetColor.java similarity index 91% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetColor.java rename to src/java/org/apache/poi/sl/draw/binding/CTPresetColor.java index 991d232d0..e240a711a 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPresetColor.java @@ -55,37 +55,37 @@ import javax.xml.bind.annotation.XmlType; public class CTPresetColor { @XmlElementRefs({ - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false) }) protected List> egColorTransform; - @XmlAttribute + @XmlAttribute(name = "val") protected STPresetColorVal val; /** @@ -106,34 +106,34 @@ public class CTPresetColor { * *

    * Objects of the following type(s) are allowed in the list + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} * * */ diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java b/src/java/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java similarity index 95% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java index 234bbd95f..b55b02ea0 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPresetGeometry2D.java @@ -52,7 +52,7 @@ public class CTPresetGeometry2D { @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") protected CTGeomGuideList avLst; - @XmlAttribute(required = true) + @XmlAttribute(name = "prst", required = true) protected STShapeType prst; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetTextShape.java b/src/java/org/apache/poi/sl/draw/binding/CTPresetTextShape.java similarity index 95% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetTextShape.java rename to src/java/org/apache/poi/sl/draw/binding/CTPresetTextShape.java index 0a6135fc9..f7082b353 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTPresetTextShape.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTPresetTextShape.java @@ -52,7 +52,7 @@ public class CTPresetTextShape { @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") protected CTGeomGuideList avLst; - @XmlAttribute(required = true) + @XmlAttribute(name = "prst", required = true) protected STTextShapeType prst; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTRatio.java b/src/java/org/apache/poi/sl/draw/binding/CTRatio.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTRatio.java rename to src/java/org/apache/poi/sl/draw/binding/CTRatio.java index 4a61b88cb..3a951c1f1 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTRatio.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTRatio.java @@ -45,9 +45,9 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_Ratio", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTRatio { - @XmlAttribute(required = true) + @XmlAttribute(name = "n", required = true) protected long n; - @XmlAttribute(required = true) + @XmlAttribute(name = "d", required = true) protected long d; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTRelativeRect.java b/src/java/org/apache/poi/sl/draw/binding/CTRelativeRect.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTRelativeRect.java rename to src/java/org/apache/poi/sl/draw/binding/CTRelativeRect.java index a8b82c474..e332bd83c 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTRelativeRect.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTRelativeRect.java @@ -47,13 +47,13 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_RelativeRect", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTRelativeRect { - @XmlAttribute + @XmlAttribute(name = "l") protected Integer l; - @XmlAttribute + @XmlAttribute(name = "t") protected Integer t; - @XmlAttribute + @XmlAttribute(name = "r") protected Integer r; - @XmlAttribute + @XmlAttribute(name = "b") protected Integer b; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSRgbColor.java b/src/java/org/apache/poi/sl/draw/binding/CTSRgbColor.java similarity index 90% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSRgbColor.java rename to src/java/org/apache/poi/sl/draw/binding/CTSRgbColor.java index c48e8370b..ef920d601 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSRgbColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTSRgbColor.java @@ -57,37 +57,37 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; public class CTSRgbColor { @XmlElementRefs({ - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false) }) protected List> egColorTransform; - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) @XmlJavaTypeAdapter(HexBinaryAdapter.class) protected byte[] val; @@ -109,34 +109,34 @@ public class CTSRgbColor { * *

    * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} * * */ @@ -176,7 +176,7 @@ public class CTSRgbColor { * */ public void setVal(byte[] value) { - this.val = ((byte[]) value); + this.val = value; } public boolean isSetVal() { diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTScRgbColor.java b/src/java/org/apache/poi/sl/draw/binding/CTScRgbColor.java similarity index 90% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTScRgbColor.java rename to src/java/org/apache/poi/sl/draw/binding/CTScRgbColor.java index 4168027e0..335e4b291 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTScRgbColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTScRgbColor.java @@ -57,41 +57,41 @@ import javax.xml.bind.annotation.XmlType; public class CTScRgbColor { @XmlElementRefs({ - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false) }) protected List> egColorTransform; - @XmlAttribute(required = true) + @XmlAttribute(name = "r", required = true) protected int r; - @XmlAttribute(required = true) + @XmlAttribute(name = "g", required = true) protected int g; - @XmlAttribute(required = true) + @XmlAttribute(name = "b", required = true) protected int b; /** @@ -113,33 +113,33 @@ public class CTScRgbColor { *

    * Objects of the following type(s) are allowed in the list * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} * * */ diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTScale2D.java b/src/java/org/apache/poi/sl/draw/binding/CTScale2D.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTScale2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTScale2D.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSchemeColor.java b/src/java/org/apache/poi/sl/draw/binding/CTSchemeColor.java similarity index 91% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSchemeColor.java rename to src/java/org/apache/poi/sl/draw/binding/CTSchemeColor.java index b93a16668..7febaad83 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSchemeColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTSchemeColor.java @@ -55,37 +55,37 @@ import javax.xml.bind.annotation.XmlType; public class CTSchemeColor { @XmlElementRefs({ - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false) }) protected List> egColorTransform; - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) protected STSchemeColorVal val; /** @@ -106,34 +106,34 @@ public class CTSchemeColor { * *

    * Objects of the following type(s) are allowed in the list - * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} * * */ diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSphereCoords.java b/src/java/org/apache/poi/sl/draw/binding/CTSphereCoords.java similarity index 92% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSphereCoords.java rename to src/java/org/apache/poi/sl/draw/binding/CTSphereCoords.java index 7f03d0dac..a29d74446 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSphereCoords.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTSphereCoords.java @@ -46,11 +46,11 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_SphereCoords", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTSphereCoords { - @XmlAttribute(required = true) + @XmlAttribute(name = "lat", required = true) protected int lat; - @XmlAttribute(required = true) + @XmlAttribute(name = "lon", required = true) protected int lon; - @XmlAttribute(required = true) + @XmlAttribute(name = "rev", required = true) protected int rev; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSystemColor.java b/src/java/org/apache/poi/sl/draw/binding/CTSystemColor.java similarity index 90% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSystemColor.java rename to src/java/org/apache/poi/sl/draw/binding/CTSystemColor.java index de94cb259..adf0d16b2 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTSystemColor.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTSystemColor.java @@ -59,40 +59,40 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; public class CTSystemColor { @XmlElementRefs({ - @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class), - @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class) + @XmlElementRef(name = "alphaMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lum", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "sat", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "red", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "invGamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "comp", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "lumOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "greenOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alphaOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "green", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "inv", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "alpha", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "shade", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "blue", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "redMod", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "hueOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gray", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "gamma", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "tint", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false), + @XmlElementRef(name = "satOff", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", type = JAXBElement.class, required = false) }) protected List> egColorTransform; - @XmlAttribute(required = true) + @XmlAttribute(name = "val", required = true) @XmlJavaTypeAdapter(CollapsedStringAdapter.class) protected String val; - @XmlAttribute + @XmlAttribute(name = "lastClr") @XmlJavaTypeAdapter(HexBinaryAdapter.class) protected byte[] lastClr; @@ -114,34 +114,34 @@ public class CTSystemColor { * *

    * Objects of the following type(s) are allowed in the list + * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} + * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} * {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >} * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >} - * {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >} - * {@link JAXBElement }{@code <}{@link CTPercentage }{@code >} + * {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >} * * */ @@ -209,7 +209,7 @@ public class CTSystemColor { * */ public void setLastClr(byte[] value) { - this.lastClr = ((byte[]) value); + this.lastClr = value; } public boolean isSetLastClr() { diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTTransform2D.java b/src/java/org/apache/poi/sl/draw/binding/CTTransform2D.java similarity index 94% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTTransform2D.java rename to src/java/org/apache/poi/sl/draw/binding/CTTransform2D.java index dd1dcb501..38ec50e65 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTTransform2D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTTransform2D.java @@ -58,11 +58,11 @@ public class CTTransform2D { protected CTPoint2D off; @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") protected CTPositiveSize2D ext; - @XmlAttribute + @XmlAttribute(name = "rot") protected Integer rot; - @XmlAttribute + @XmlAttribute(name = "flipH") protected Boolean flipH; - @XmlAttribute + @XmlAttribute(name = "flipV") protected Boolean flipV; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTVector3D.java b/src/java/org/apache/poi/sl/draw/binding/CTVector3D.java similarity index 92% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTVector3D.java rename to src/java/org/apache/poi/sl/draw/binding/CTVector3D.java index d7f744ba6..03c5fb8e4 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTVector3D.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTVector3D.java @@ -46,11 +46,11 @@ import javax.xml.bind.annotation.XmlType; @XmlType(name = "CT_Vector3D", namespace = "http://schemas.openxmlformats.org/drawingml/2006/main") public class CTVector3D { - @XmlAttribute(required = true) + @XmlAttribute(name = "dx", required = true) protected long dx; - @XmlAttribute(required = true) + @XmlAttribute(name = "dy", required = true) protected long dy; - @XmlAttribute(required = true) + @XmlAttribute(name = "dz", required = true) protected long dz; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java b/src/java/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java similarity index 93% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java rename to src/java/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java index 2b22a5881..85c30bac5 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java +++ b/src/java/org/apache/poi/sl/draw/binding/CTXYAdjustHandle.java @@ -59,19 +59,19 @@ public class CTXYAdjustHandle { @XmlElement(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", required = true) protected CTAdjPoint2D pos; - @XmlAttribute + @XmlAttribute(name = "gdRefX") @XmlJavaTypeAdapter(CollapsedStringAdapter.class) protected String gdRefX; - @XmlAttribute + @XmlAttribute(name = "minX") protected String minX; - @XmlAttribute + @XmlAttribute(name = "maxX") protected String maxX; - @XmlAttribute + @XmlAttribute(name = "gdRefY") @XmlJavaTypeAdapter(CollapsedStringAdapter.class) protected String gdRefY; - @XmlAttribute + @XmlAttribute(name = "minY") protected String minY; - @XmlAttribute + @XmlAttribute(name = "maxY") protected String maxY; /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/ObjectFactory.java b/src/java/org/apache/poi/sl/draw/binding/ObjectFactory.java similarity index 75% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/ObjectFactory.java rename to src/java/org/apache/poi/sl/draw/binding/ObjectFactory.java index c8c8c19d8..8c6f9c217 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/binding/ObjectFactory.java +++ b/src/java/org/apache/poi/sl/draw/binding/ObjectFactory.java @@ -40,34 +40,34 @@ import javax.xml.namespace.QName; @XmlRegistry public class ObjectFactory { - private final static QName _CTScRgbColorAlpha_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alpha"); - private final static QName _CTScRgbColorLum_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lum"); - private final static QName _CTScRgbColorGamma_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "gamma"); - private final static QName _CTScRgbColorInvGamma_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "invGamma"); - private final static QName _CTScRgbColorAlphaMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alphaMod"); - private final static QName _CTScRgbColorRedOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "redOff"); - private final static QName _CTScRgbColorAlphaOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alphaOff"); - private final static QName _CTScRgbColorGreenOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "greenOff"); - private final static QName _CTScRgbColorRedMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "redMod"); - private final static QName _CTScRgbColorHue_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hue"); - private final static QName _CTScRgbColorSatOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "satOff"); - private final static QName _CTScRgbColorGreenMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "greenMod"); - private final static QName _CTScRgbColorSat_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "sat"); - private final static QName _CTScRgbColorBlue_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blue"); - private final static QName _CTScRgbColorRed_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "red"); - private final static QName _CTScRgbColorSatMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "satMod"); - private final static QName _CTScRgbColorHueOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hueOff"); - private final static QName _CTScRgbColorBlueMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blueMod"); - private final static QName _CTScRgbColorShade_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "shade"); - private final static QName _CTScRgbColorLumMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lumMod"); - private final static QName _CTScRgbColorInv_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "inv"); - private final static QName _CTScRgbColorLumOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lumOff"); - private final static QName _CTScRgbColorTint_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tint"); - private final static QName _CTScRgbColorGreen_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "green"); - private final static QName _CTScRgbColorComp_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "comp"); - private final static QName _CTScRgbColorBlueOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blueOff"); - private final static QName _CTScRgbColorHueMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hueMod"); - private final static QName _CTScRgbColorGray_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "gray"); + private final static QName _CTSRgbColorAlpha_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alpha"); + private final static QName _CTSRgbColorLum_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lum"); + private final static QName _CTSRgbColorGamma_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "gamma"); + private final static QName _CTSRgbColorInvGamma_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "invGamma"); + private final static QName _CTSRgbColorAlphaMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alphaMod"); + private final static QName _CTSRgbColorRedOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "redOff"); + private final static QName _CTSRgbColorAlphaOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "alphaOff"); + private final static QName _CTSRgbColorGreenOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "greenOff"); + private final static QName _CTSRgbColorHue_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hue"); + private final static QName _CTSRgbColorRedMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "redMod"); + private final static QName _CTSRgbColorSatOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "satOff"); + private final static QName _CTSRgbColorGreenMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "greenMod"); + private final static QName _CTSRgbColorSat_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "sat"); + private final static QName _CTSRgbColorBlue_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blue"); + private final static QName _CTSRgbColorRed_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "red"); + private final static QName _CTSRgbColorSatMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "satMod"); + private final static QName _CTSRgbColorBlueMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blueMod"); + private final static QName _CTSRgbColorHueOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hueOff"); + private final static QName _CTSRgbColorShade_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "shade"); + private final static QName _CTSRgbColorLumMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lumMod"); + private final static QName _CTSRgbColorInv_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "inv"); + private final static QName _CTSRgbColorLumOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "lumOff"); + private final static QName _CTSRgbColorTint_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tint"); + private final static QName _CTSRgbColorGreen_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "green"); + private final static QName _CTSRgbColorComp_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "comp"); + private final static QName _CTSRgbColorBlueOff_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "blueOff"); + private final static QName _CTSRgbColorHueMod_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "hueMod"); + private final static QName _CTSRgbColorGray_QNAME = new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "gray"); /** * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.poi.sl.draw.binding @@ -76,62 +76,6 @@ public class ObjectFactory { public ObjectFactory() { } - /** - * Create an instance of {@link CTOfficeArtExtensionList } - * - */ - public CTOfficeArtExtensionList createCTOfficeArtExtensionList() { - return new CTOfficeArtExtensionList(); - } - - /** - * Create an instance of {@link CTPresetGeometry2D } - * - */ - public CTPresetGeometry2D createCTPresetGeometry2D() { - return new CTPresetGeometry2D(); - } - - /** - * Create an instance of {@link CTPath2D } - * - */ - public CTPath2D createCTPath2D() { - return new CTPath2D(); - } - - /** - * Create an instance of {@link CTVector3D } - * - */ - public CTVector3D createCTVector3D() { - return new CTVector3D(); - } - - /** - * Create an instance of {@link CTGammaTransform } - * - */ - public CTGammaTransform createCTGammaTransform() { - return new CTGammaTransform(); - } - - /** - * Create an instance of {@link CTColorMRU } - * - */ - public CTColorMRU createCTColorMRU() { - return new CTColorMRU(); - } - - /** - * Create an instance of {@link CTEmbeddedWAVAudioFile } - * - */ - public CTEmbeddedWAVAudioFile createCTEmbeddedWAVAudioFile() { - return new CTEmbeddedWAVAudioFile(); - } - /** * Create an instance of {@link CTPath2DQuadBezierTo } * @@ -140,70 +84,6 @@ public class ObjectFactory { return new CTPath2DQuadBezierTo(); } - /** - * Create an instance of {@link CTScRgbColor } - * - */ - public CTScRgbColor createCTScRgbColor() { - return new CTScRgbColor(); - } - - /** - * Create an instance of {@link CTPositiveFixedAngle } - * - */ - public CTPositiveFixedAngle createCTPositiveFixedAngle() { - return new CTPositiveFixedAngle(); - } - - /** - * Create an instance of {@link CTGeomGuide } - * - */ - public CTGeomGuide createCTGeomGuide() { - return new CTGeomGuide(); - } - - /** - * Create an instance of {@link CTConnectionSiteList } - * - */ - public CTConnectionSiteList createCTConnectionSiteList() { - return new CTConnectionSiteList(); - } - - /** - * Create an instance of {@link CTPercentage } - * - */ - public CTPercentage createCTPercentage() { - return new CTPercentage(); - } - - /** - * Create an instance of {@link CTPositiveFixedPercentage } - * - */ - public CTPositiveFixedPercentage createCTPositiveFixedPercentage() { - return new CTPositiveFixedPercentage(); - } - - /** - * Create an instance of {@link CTPath2DMoveTo } - * - */ - public CTPath2DMoveTo createCTPath2DMoveTo() { - return new CTPath2DMoveTo(); - } - - /** - * Create an instance of {@link CTPath2DList } - * - */ - public CTPath2DList createCTPath2DList() { - return new CTPath2DList(); - } - /** * Create an instance of {@link CTCustomGeometry2D } * @@ -212,46 +92,6 @@ public class ObjectFactory { return new CTCustomGeometry2D(); } - /** - * Create an instance of {@link CTConnectionSite } - * - */ - public CTConnectionSite createCTConnectionSite() { - return new CTConnectionSite(); - } - - /** - * Create an instance of {@link CTGrayscaleTransform } - * - */ - public CTGrayscaleTransform createCTGrayscaleTransform() { - return new CTGrayscaleTransform(); - } - - /** - * Create an instance of {@link CTInverseTransform } - * - */ - public CTInverseTransform createCTInverseTransform() { - return new CTInverseTransform(); - } - - /** - * Create an instance of {@link CTPositiveSize2D } - * - */ - public CTPositiveSize2D createCTPositiveSize2D() { - return new CTPositiveSize2D(); - } - - /** - * Create an instance of {@link CTRelativeRect } - * - */ - public CTRelativeRect createCTRelativeRect() { - return new CTRelativeRect(); - } - /** * Create an instance of {@link CTPolarAdjustHandle } * @@ -260,86 +100,6 @@ public class ObjectFactory { return new CTPolarAdjustHandle(); } - /** - * Create an instance of {@link CTRatio } - * - */ - public CTRatio createCTRatio() { - return new CTRatio(); - } - - /** - * Create an instance of {@link CTInverseGammaTransform } - * - */ - public CTInverseGammaTransform createCTInverseGammaTransform() { - return new CTInverseGammaTransform(); - } - - /** - * Create an instance of {@link CTGroupTransform2D } - * - */ - public CTGroupTransform2D createCTGroupTransform2D() { - return new CTGroupTransform2D(); - } - - /** - * Create an instance of {@link CTGeomRect } - * - */ - public CTGeomRect createCTGeomRect() { - return new CTGeomRect(); - } - - /** - * Create an instance of {@link CTSystemColor } - * - */ - public CTSystemColor createCTSystemColor() { - return new CTSystemColor(); - } - - /** - * Create an instance of {@link CTAdjPoint2D } - * - */ - public CTAdjPoint2D createCTAdjPoint2D() { - return new CTAdjPoint2D(); - } - - /** - * Create an instance of {@link CTPath2DCubicBezierTo } - * - */ - public CTPath2DCubicBezierTo createCTPath2DCubicBezierTo() { - return new CTPath2DCubicBezierTo(); - } - - /** - * Create an instance of {@link CTPath2DArcTo } - * - */ - public CTPath2DArcTo createCTPath2DArcTo() { - return new CTPath2DArcTo(); - } - - /** - * Create an instance of {@link CTGeomGuideList } - * - */ - public CTGeomGuideList createCTGeomGuideList() { - return new CTGeomGuideList(); - } - - /** - * Create an instance of {@link CTAdjustHandleList } - * - */ - public CTAdjustHandleList createCTAdjustHandleList() { - return new CTAdjustHandleList(); - } - /** * Create an instance of {@link CTPath2DClose } * @@ -348,62 +108,6 @@ public class ObjectFactory { return new CTPath2DClose(); } - /** - * Create an instance of {@link CTPresetTextShape } - * - */ - public CTPresetTextShape createCTPresetTextShape() { - return new CTPresetTextShape(); - } - - /** - * Create an instance of {@link CTConnection } - * - */ - public CTConnection createCTConnection() { - return new CTConnection(); - } - - /** - * Create an instance of {@link CTSRgbColor } - * - */ - public CTSRgbColor createCTSRgbColor() { - return new CTSRgbColor(); - } - - /** - * Create an instance of {@link CTPositivePercentage } - * - */ - public CTPositivePercentage createCTPositivePercentage() { - return new CTPositivePercentage(); - } - - /** - * Create an instance of {@link CTComplementTransform } - * - */ - public CTComplementTransform createCTComplementTransform() { - return new CTComplementTransform(); - } - - /** - * Create an instance of {@link CTScale2D } - * - */ - public CTScale2D createCTScale2D() { - return new CTScale2D(); - } - - /** - * Create an instance of {@link CTFixedPercentage } - * - */ - public CTFixedPercentage createCTFixedPercentage() { - return new CTFixedPercentage(); - } - /** * Create an instance of {@link CTPoint2D } * @@ -412,6 +116,38 @@ public class ObjectFactory { return new CTPoint2D(); } + /** + * Create an instance of {@link CTInverseTransform } + * + */ + public CTInverseTransform createCTInverseTransform() { + return new CTInverseTransform(); + } + + /** + * Create an instance of {@link CTPercentage } + * + */ + public CTPercentage createCTPercentage() { + return new CTPercentage(); + } + + /** + * Create an instance of {@link CTSystemColor } + * + */ + public CTSystemColor createCTSystemColor() { + return new CTSystemColor(); + } + + /** + * Create an instance of {@link CTConnectionSite } + * + */ + public CTConnectionSite createCTConnectionSite() { + return new CTConnectionSite(); + } + /** * Create an instance of {@link CTColor } * @@ -421,11 +157,19 @@ public class ObjectFactory { } /** - * Create an instance of {@link CTPoint3D } + * Create an instance of {@link CTPositiveFixedAngle } * */ - public CTPoint3D createCTPoint3D() { - return new CTPoint3D(); + public CTPositiveFixedAngle createCTPositiveFixedAngle() { + return new CTPositiveFixedAngle(); + } + + /** + * Create an instance of {@link CTFixedPercentage } + * + */ + public CTFixedPercentage createCTFixedPercentage() { + return new CTFixedPercentage(); } /** @@ -436,6 +180,22 @@ public class ObjectFactory { return new CTHslColor(); } + /** + * Create an instance of {@link CTConnection } + * + */ + public CTConnection createCTConnection() { + return new CTConnection(); + } + + /** + * Create an instance of {@link CTPath2DLineTo } + * + */ + public CTPath2DLineTo createCTPath2DLineTo() { + return new CTPath2DLineTo(); + } + /** * Create an instance of {@link CTTransform2D } * @@ -444,6 +204,110 @@ public class ObjectFactory { return new CTTransform2D(); } + /** + * Create an instance of {@link CTPositivePercentage } + * + */ + public CTPositivePercentage createCTPositivePercentage() { + return new CTPositivePercentage(); + } + + /** + * Create an instance of {@link CTVector3D } + * + */ + public CTVector3D createCTVector3D() { + return new CTVector3D(); + } + + /** + * Create an instance of {@link CTSphereCoords } + * + */ + public CTSphereCoords createCTSphereCoords() { + return new CTSphereCoords(); + } + + /** + * Create an instance of {@link CTPath2D } + * + */ + public CTPath2D createCTPath2D() { + return new CTPath2D(); + } + + /** + * Create an instance of {@link CTGroupTransform2D } + * + */ + public CTGroupTransform2D createCTGroupTransform2D() { + return new CTGroupTransform2D(); + } + + /** + * Create an instance of {@link CTGrayscaleTransform } + * + */ + public CTGrayscaleTransform createCTGrayscaleTransform() { + return new CTGrayscaleTransform(); + } + + /** + * Create an instance of {@link CTRatio } + * + */ + public CTRatio createCTRatio() { + return new CTRatio(); + } + + /** + * Create an instance of {@link CTSRgbColor } + * + */ + public CTSRgbColor createCTSRgbColor() { + return new CTSRgbColor(); + } + + /** + * Create an instance of {@link CTGeomGuideList } + * + */ + public CTGeomGuideList createCTGeomGuideList() { + return new CTGeomGuideList(); + } + + /** + * Create an instance of {@link CTComplementTransform } + * + */ + public CTComplementTransform createCTComplementTransform() { + return new CTComplementTransform(); + } + + /** + * Create an instance of {@link CTPath2DCubicBezierTo } + * + */ + public CTPath2DCubicBezierTo createCTPath2DCubicBezierTo() { + return new CTPath2DCubicBezierTo(); + } + + /** + * Create an instance of {@link CTXYAdjustHandle } + * + */ + public CTXYAdjustHandle createCTXYAdjustHandle() { + return new CTXYAdjustHandle(); + } + + /** + * Create an instance of {@link CTPresetColor } + * + */ + public CTPresetColor createCTPresetColor() { + return new CTPresetColor(); + } + /** * Create an instance of {@link CTOfficeArtExtension } * @@ -461,43 +325,27 @@ public class ObjectFactory { } /** - * Create an instance of {@link CTSphereCoords } + * Create an instance of {@link CTConnectionSiteList } * */ - public CTSphereCoords createCTSphereCoords() { - return new CTSphereCoords(); + public CTConnectionSiteList createCTConnectionSiteList() { + return new CTConnectionSiteList(); } /** - * Create an instance of {@link CTXYAdjustHandle } + * Create an instance of {@link CTPath2DArcTo } * */ - public CTXYAdjustHandle createCTXYAdjustHandle() { - return new CTXYAdjustHandle(); + public CTPath2DArcTo createCTPath2DArcTo() { + return new CTPath2DArcTo(); } /** - * Create an instance of {@link CTHyperlink } + * Create an instance of {@link CTPath2DList } * */ - public CTHyperlink createCTHyperlink() { - return new CTHyperlink(); - } - - /** - * Create an instance of {@link CTPath2DLineTo } - * - */ - public CTPath2DLineTo createCTPath2DLineTo() { - return new CTPath2DLineTo(); - } - - /** - * Create an instance of {@link CTPresetColor } - * - */ - public CTPresetColor createCTPresetColor() { - return new CTPresetColor(); + public CTPath2DList createCTPath2DList() { + return new CTPath2DList(); } /** @@ -509,1011 +357,155 @@ public class ObjectFactory { } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * Create an instance of {@link CTScale2D } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); + public CTScale2D createCTScale2D() { + return new CTScale2D(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTPositiveSize2D } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorLum(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLum_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTPositiveSize2D createCTPositiveSize2D() { + return new CTPositiveSize2D(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * Create an instance of {@link CTOfficeArtExtensionList } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTScRgbColorGamma_QNAME, CTGammaTransform.class, CTScRgbColor.class, value); + public CTOfficeArtExtensionList createCTOfficeArtExtensionList() { + return new CTOfficeArtExtensionList(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * Create an instance of {@link CTHyperlink } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTScRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTScRgbColor.class, value); + public CTHyperlink createCTHyperlink() { + return new CTHyperlink(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * Create an instance of {@link CTPoint3D } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTScRgbColor.class, value); + public CTPoint3D createCTPoint3D() { + return new CTPoint3D(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTInverseGammaTransform } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorRedOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTInverseGammaTransform createCTInverseGammaTransform() { + return new CTInverseGammaTransform(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * Create an instance of {@link CTPositiveFixedPercentage } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTScRgbColor.class, value); + public CTPositiveFixedPercentage createCTPositiveFixedPercentage() { + return new CTPositiveFixedPercentage(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTGeomRect } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTGeomRect createCTGeomRect() { + return new CTGeomRect(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTPresetTextShape } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorRedMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTPresetTextShape createCTPresetTextShape() { + return new CTPresetTextShape(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * Create an instance of {@link CTColorMRU } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTScRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTScRgbColor.class, value); + public CTColorMRU createCTColorMRU() { + return new CTColorMRU(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTPath2DMoveTo } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorSatOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTPath2DMoveTo createCTPath2DMoveTo() { + return new CTPath2DMoveTo(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTEmbeddedWAVAudioFile } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTEmbeddedWAVAudioFile createCTEmbeddedWAVAudioFile() { + return new CTEmbeddedWAVAudioFile(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTScRgbColor } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorSat(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSat_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTScRgbColor createCTScRgbColor() { + return new CTScRgbColor(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTPresetGeometry2D } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorBlue(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlue_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTPresetGeometry2D createCTPresetGeometry2D() { + return new CTPresetGeometry2D(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTGeomGuide } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorRed(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRed_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTGeomGuide createCTGeomGuide() { + return new CTGeomGuide(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTRelativeRect } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorSatMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTRelativeRect createCTRelativeRect() { + return new CTRelativeRect(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * Create an instance of {@link CTAdjustHandleList } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorHueOff(CTAngle value) { - return new JAXBElement(_CTScRgbColorHueOff_QNAME, CTAngle.class, CTScRgbColor.class, value); + public CTAdjustHandleList createCTAdjustHandleList() { + return new CTAdjustHandleList(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * Create an instance of {@link CTAdjPoint2D } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + public CTAdjPoint2D createCTAdjPoint2D() { + return new CTAdjPoint2D(); } /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * Create an instance of {@link CTGammaTransform } * */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorLumMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorInv(CTInverseTransform value) { - return new JAXBElement(_CTScRgbColorInv_QNAME, CTInverseTransform.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorLumOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGreen(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreen_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorComp(CTComplementTransform value) { - return new JAXBElement(_CTScRgbColorComp_QNAME, CTComplementTransform.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorHueMod_QNAME, CTPositivePercentage.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTScRgbColor.class) - public JAXBElement createCTScRgbColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTScRgbColorGray_QNAME, CTGrayscaleTransform.class, CTScRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTHslColor.class) - public JAXBElement createCTHslColorLum(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLum_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTHslColor.class) - public JAXBElement createCTHslColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTHslColor.class) - public JAXBElement createCTHslColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTScRgbColorGamma_QNAME, CTGammaTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTHslColor.class) - public JAXBElement createCTHslColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTScRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorRedOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTHslColor.class) - public JAXBElement createCTHslColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTScRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorRedMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorSatOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTHslColor.class) - public JAXBElement createCTHslColorBlue(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlue_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTHslColor.class) - public JAXBElement createCTHslColorSat(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSat_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTHslColor.class) - public JAXBElement createCTHslColorRed(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRed_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorSatMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorHueOff(CTAngle value) { - return new JAXBElement(_CTScRgbColorHueOff_QNAME, CTAngle.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTHslColor.class) - public JAXBElement createCTHslColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorLumMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumMod_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTHslColor.class) - public JAXBElement createCTHslColorInv(CTInverseTransform value) { - return new JAXBElement(_CTScRgbColorInv_QNAME, CTInverseTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorLumOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTHslColor.class) - public JAXBElement createCTHslColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTHslColor.class) - public JAXBElement createCTHslColorGreen(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreen_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTHslColor.class) - public JAXBElement createCTHslColorComp(CTComplementTransform value) { - return new JAXBElement(_CTScRgbColorComp_QNAME, CTComplementTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTHslColor.class) - public JAXBElement createCTHslColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueOff_QNAME, CTPercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTHslColor.class) - public JAXBElement createCTHslColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorHueMod_QNAME, CTPositivePercentage.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTHslColor.class) - public JAXBElement createCTHslColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTScRgbColorGray_QNAME, CTGrayscaleTransform.class, CTHslColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorLum(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLum_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTScRgbColorGamma_QNAME, CTGammaTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTScRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorRedOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorRedMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTScRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorSatOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorBlue(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlue_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorSat(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSat_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorRed(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRed_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorSatMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorHueOff(CTAngle value) { - return new JAXBElement(_CTScRgbColorHueOff_QNAME, CTAngle.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorLumMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumMod_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorInv(CTInverseTransform value) { - return new JAXBElement(_CTScRgbColorInv_QNAME, CTInverseTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorLumOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGreen(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreen_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorComp(CTComplementTransform value) { - return new JAXBElement(_CTScRgbColorComp_QNAME, CTComplementTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueOff_QNAME, CTPercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSystemColor.class) - public JAXBElement createCTSystemColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTScRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSystemColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorLum(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLum_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTScRgbColorGamma_QNAME, CTGammaTransform.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTScRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorRedOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTScRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorRedMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorSatOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorSat(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSat_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorBlue(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlue_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorRed(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRed_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorSatMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorHueOff(CTAngle value) { - return new JAXBElement(_CTScRgbColorHueOff_QNAME, CTAngle.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorLumMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumMod_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorInv(CTInverseTransform value) { - return new JAXBElement(_CTScRgbColorInv_QNAME, CTInverseTransform.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorLumOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGreen(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreen_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorComp(CTComplementTransform value) { - return new JAXBElement(_CTScRgbColorComp_QNAME, CTComplementTransform.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueOff_QNAME, CTPercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorHueMod_QNAME, CTPositivePercentage.class, CTPresetColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTPresetColor.class) - public JAXBElement createCTPresetColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTScRgbColorGray_QNAME, CTGrayscaleTransform.class, CTPresetColor.class, value); + public CTGammaTransform createCTGammaTransform() { + return new CTGammaTransform(); } /** @@ -1522,7 +514,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); } /** @@ -1531,7 +523,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorLum(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLum_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1540,7 +532,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTScRgbColorGamma_QNAME, CTGammaTransform.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSRgbColor.class, value); } /** @@ -1549,7 +541,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTScRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSRgbColor.class, value); } /** @@ -1558,7 +550,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSRgbColor.class, value); } /** @@ -1567,7 +559,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorRedOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1576,7 +568,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSRgbColor.class, value); } /** @@ -1585,16 +577,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorRedMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1603,7 +586,16 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTScRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1612,7 +604,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorSatOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1621,16 +613,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorBlue(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlue_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1639,7 +622,16 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorSat(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSat_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1648,7 +640,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorRed(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRed_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1657,16 +649,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorSatMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSRgbColor.class) - public JAXBElement createCTSRgbColorHueOff(CTAngle value) { - return new JAXBElement(_CTScRgbColorHueOff_QNAME, CTAngle.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1675,7 +658,16 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSRgbColor.class) + public JAXBElement createCTSRgbColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSRgbColor.class, value); } /** @@ -1684,7 +676,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); } /** @@ -1693,7 +685,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorLumMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1702,7 +694,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorInv(CTInverseTransform value) { - return new JAXBElement(_CTScRgbColorInv_QNAME, CTInverseTransform.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSRgbColor.class, value); } /** @@ -1711,7 +703,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorLumOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1720,7 +712,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSRgbColor.class, value); } /** @@ -1729,7 +721,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorGreen(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreen_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1738,7 +730,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorComp(CTComplementTransform value) { - return new JAXBElement(_CTScRgbColorComp_QNAME, CTComplementTransform.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSRgbColor.class, value); } /** @@ -1747,7 +739,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSRgbColor.class, value); } /** @@ -1756,7 +748,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSRgbColor.class, value); } /** @@ -1765,7 +757,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSRgbColor.class) public JAXBElement createCTSRgbColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTScRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSRgbColor.class, value); + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSRgbColor.class, value); } /** @@ -1774,7 +766,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorAlpha(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); } /** @@ -1783,7 +775,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorLum(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLum_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1792,7 +784,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorGamma(CTGammaTransform value) { - return new JAXBElement(_CTScRgbColorGamma_QNAME, CTGammaTransform.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSchemeColor.class, value); } /** @@ -1801,16 +793,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorInvGamma(CTInverseGammaTransform value) { - return new JAXBElement(_CTScRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorRedOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSchemeColor.class, value); } /** @@ -1819,7 +802,16 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorAlphaMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1828,7 +820,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorAlphaOff(CTFixedPercentage value) { - return new JAXBElement(_CTScRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSchemeColor.class, value); } /** @@ -1837,16 +829,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorGreenOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); - } - - /** - * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} - * - */ - @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSchemeColor.class) - public JAXBElement createCTSchemeColorRedMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRedMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1855,7 +838,16 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorHue(CTPositiveFixedAngle value) { - return new JAXBElement(_CTScRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSchemeColor.class) + public JAXBElement createCTSchemeColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1864,7 +856,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorSatOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1873,7 +865,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorGreenMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreenMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1882,7 +874,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorSat(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSat_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1891,7 +883,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorBlue(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlue_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1900,7 +892,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorRed(CTPercentage value) { - return new JAXBElement(_CTScRgbColorRed_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1909,7 +901,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorSatMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorSatMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1918,7 +910,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorBlueMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1927,7 +919,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorHueOff(CTAngle value) { - return new JAXBElement(_CTScRgbColorHueOff_QNAME, CTAngle.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSchemeColor.class, value); } /** @@ -1936,7 +928,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorShade(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); } /** @@ -1945,7 +937,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorLumMod(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1954,7 +946,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorInv(CTInverseTransform value) { - return new JAXBElement(_CTScRgbColorInv_QNAME, CTInverseTransform.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSchemeColor.class, value); } /** @@ -1963,7 +955,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorLumOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorLumOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1972,7 +964,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorTint(CTPositiveFixedPercentage value) { - return new JAXBElement(_CTScRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSchemeColor.class, value); } /** @@ -1981,7 +973,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorGreen(CTPercentage value) { - return new JAXBElement(_CTScRgbColorGreen_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -1990,7 +982,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorComp(CTComplementTransform value) { - return new JAXBElement(_CTScRgbColorComp_QNAME, CTComplementTransform.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSchemeColor.class, value); } /** @@ -1999,7 +991,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorBlueOff(CTPercentage value) { - return new JAXBElement(_CTScRgbColorBlueOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSchemeColor.class, value); } /** @@ -2008,7 +1000,7 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorHueMod(CTPositivePercentage value) { - return new JAXBElement(_CTScRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSchemeColor.class, value); } /** @@ -2017,7 +1009,1015 @@ public class ObjectFactory { */ @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSchemeColor.class) public JAXBElement createCTSchemeColorGray(CTGrayscaleTransform value) { - return new JAXBElement(_CTScRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSchemeColor.class, value); + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSchemeColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTScRgbColor.class) + public JAXBElement createCTScRgbColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTScRgbColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTSystemColor.class) + public JAXBElement createCTSystemColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTSystemColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTHslColor.class) + public JAXBElement createCTHslColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTHslColor.class) + public JAXBElement createCTHslColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTHslColor.class) + public JAXBElement createCTHslColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTHslColor.class) + public JAXBElement createCTHslColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTHslColor.class) + public JAXBElement createCTHslColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTHslColor.class) + public JAXBElement createCTHslColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTHslColor.class) + public JAXBElement createCTHslColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTHslColor.class) + public JAXBElement createCTHslColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTHslColor.class) + public JAXBElement createCTHslColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTHslColor.class) + public JAXBElement createCTHslColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTHslColor.class) + public JAXBElement createCTHslColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTHslColor.class) + public JAXBElement createCTHslColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTHslColor.class) + public JAXBElement createCTHslColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTHslColor.class) + public JAXBElement createCTHslColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTHslColor.class) + public JAXBElement createCTHslColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTHslColor.class) + public JAXBElement createCTHslColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTHslColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alpha", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorAlpha(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlpha_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lum", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorLum(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLum_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gamma", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGamma(CTGammaTransform value) { + return new JAXBElement(_CTSRgbColorGamma_QNAME, CTGammaTransform.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseGammaTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "invGamma", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorInvGamma(CTInverseGammaTransform value) { + return new JAXBElement(_CTSRgbColorInvGamma_QNAME, CTInverseGammaTransform.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorAlphaMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorAlphaMod_QNAME, CTPositivePercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorRedOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "alphaOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorAlphaOff(CTFixedPercentage value) { + return new JAXBElement(_CTSRgbColorAlphaOff_QNAME, CTFixedPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGreenOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hue", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorHue(CTPositiveFixedAngle value) { + return new JAXBElement(_CTSRgbColorHue_QNAME, CTPositiveFixedAngle.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "redMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorRedMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRedMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorSatOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "greenMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGreenMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreenMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "sat", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorSat(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSat_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blue", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorBlue(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlue_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "red", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorRed(CTPercentage value) { + return new JAXBElement(_CTSRgbColorRed_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "satMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorSatMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorSatMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorBlueMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTAngle }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorHueOff(CTAngle value) { + return new JAXBElement(_CTSRgbColorHueOff_QNAME, CTAngle.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "shade", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorShade(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorShade_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorLumMod(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumMod_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTInverseTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "inv", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorInv(CTInverseTransform value) { + return new JAXBElement(_CTSRgbColorInv_QNAME, CTInverseTransform.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "lumOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorLumOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorLumOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositiveFixedPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "tint", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorTint(CTPositiveFixedPercentage value) { + return new JAXBElement(_CTSRgbColorTint_QNAME, CTPositiveFixedPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "green", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGreen(CTPercentage value) { + return new JAXBElement(_CTSRgbColorGreen_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTComplementTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "comp", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorComp(CTComplementTransform value) { + return new JAXBElement(_CTSRgbColorComp_QNAME, CTComplementTransform.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "blueOff", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorBlueOff(CTPercentage value) { + return new JAXBElement(_CTSRgbColorBlueOff_QNAME, CTPercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTPositivePercentage }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "hueMod", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorHueMod(CTPositivePercentage value) { + return new JAXBElement(_CTSRgbColorHueMod_QNAME, CTPositivePercentage.class, CTPresetColor.class, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CTGrayscaleTransform }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://schemas.openxmlformats.org/drawingml/2006/main", name = "gray", scope = CTPresetColor.class) + public JAXBElement createCTPresetColorGray(CTGrayscaleTransform value) { + return new JAXBElement(_CTSRgbColorGray_QNAME, CTGrayscaleTransform.class, CTPresetColor.class, value); } } diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/STBlackWhiteMode.java b/src/java/org/apache/poi/sl/draw/binding/STBlackWhiteMode.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/STBlackWhiteMode.java rename to src/java/org/apache/poi/sl/draw/binding/STBlackWhiteMode.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/STPathFillMode.java b/src/java/org/apache/poi/sl/draw/binding/STPathFillMode.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/STPathFillMode.java rename to src/java/org/apache/poi/sl/draw/binding/STPathFillMode.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/STPresetColorVal.java b/src/java/org/apache/poi/sl/draw/binding/STPresetColorVal.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/STPresetColorVal.java rename to src/java/org/apache/poi/sl/draw/binding/STPresetColorVal.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/STRectAlignment.java b/src/java/org/apache/poi/sl/draw/binding/STRectAlignment.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/STRectAlignment.java rename to src/java/org/apache/poi/sl/draw/binding/STRectAlignment.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/STSchemeColorVal.java b/src/java/org/apache/poi/sl/draw/binding/STSchemeColorVal.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/STSchemeColorVal.java rename to src/java/org/apache/poi/sl/draw/binding/STSchemeColorVal.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/STShapeType.java b/src/java/org/apache/poi/sl/draw/binding/STShapeType.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/STShapeType.java rename to src/java/org/apache/poi/sl/draw/binding/STShapeType.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/binding/STTextShapeType.java b/src/java/org/apache/poi/sl/draw/binding/STTextShapeType.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/binding/STTextShapeType.java rename to src/java/org/apache/poi/sl/draw/binding/STTextShapeType.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/AbsExpression.java b/src/java/org/apache/poi/sl/draw/geom/AbsExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/AbsExpression.java rename to src/java/org/apache/poi/sl/draw/geom/AbsExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/AddDivideExpression.java b/src/java/org/apache/poi/sl/draw/geom/AddDivideExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/AddDivideExpression.java rename to src/java/org/apache/poi/sl/draw/geom/AddDivideExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/AddSubtractExpression.java b/src/java/org/apache/poi/sl/draw/geom/AddSubtractExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/AddSubtractExpression.java rename to src/java/org/apache/poi/sl/draw/geom/AddSubtractExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/AdjustValue.java b/src/java/org/apache/poi/sl/draw/geom/AdjustValue.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/AdjustValue.java rename to src/java/org/apache/poi/sl/draw/geom/AdjustValue.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/ArcTanExpression.java b/src/java/org/apache/poi/sl/draw/geom/ArcTanExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/ArcTanExpression.java rename to src/java/org/apache/poi/sl/draw/geom/ArcTanExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/ArcToCommand.java b/src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/ArcToCommand.java rename to src/java/org/apache/poi/sl/draw/geom/ArcToCommand.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/ClosePathCommand.java b/src/java/org/apache/poi/sl/draw/geom/ClosePathCommand.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/ClosePathCommand.java rename to src/java/org/apache/poi/sl/draw/geom/ClosePathCommand.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/Context.java b/src/java/org/apache/poi/sl/draw/geom/Context.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/Context.java rename to src/java/org/apache/poi/sl/draw/geom/Context.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/CosExpression.java b/src/java/org/apache/poi/sl/draw/geom/CosExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/CosExpression.java rename to src/java/org/apache/poi/sl/draw/geom/CosExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/CosineArcTanExpression.java b/src/java/org/apache/poi/sl/draw/geom/CosineArcTanExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/CosineArcTanExpression.java rename to src/java/org/apache/poi/sl/draw/geom/CosineArcTanExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/CurveToCommand.java b/src/java/org/apache/poi/sl/draw/geom/CurveToCommand.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/CurveToCommand.java rename to src/java/org/apache/poi/sl/draw/geom/CurveToCommand.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/CustomGeometry.java b/src/java/org/apache/poi/sl/draw/geom/CustomGeometry.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/CustomGeometry.java rename to src/java/org/apache/poi/sl/draw/geom/CustomGeometry.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/Expression.java b/src/java/org/apache/poi/sl/draw/geom/Expression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/Expression.java rename to src/java/org/apache/poi/sl/draw/geom/Expression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/ExpressionParser.java b/src/java/org/apache/poi/sl/draw/geom/ExpressionParser.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/ExpressionParser.java rename to src/java/org/apache/poi/sl/draw/geom/ExpressionParser.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/Formula.java b/src/java/org/apache/poi/sl/draw/geom/Formula.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/Formula.java rename to src/java/org/apache/poi/sl/draw/geom/Formula.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/Guide.java b/src/java/org/apache/poi/sl/draw/geom/Guide.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/Guide.java rename to src/java/org/apache/poi/sl/draw/geom/Guide.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/IAdjustableShape.java b/src/java/org/apache/poi/sl/draw/geom/IAdjustableShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/IAdjustableShape.java rename to src/java/org/apache/poi/sl/draw/geom/IAdjustableShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/IfElseExpression.java b/src/java/org/apache/poi/sl/draw/geom/IfElseExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/IfElseExpression.java rename to src/java/org/apache/poi/sl/draw/geom/IfElseExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/LineToCommand.java b/src/java/org/apache/poi/sl/draw/geom/LineToCommand.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/LineToCommand.java rename to src/java/org/apache/poi/sl/draw/geom/LineToCommand.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/LiteralValueExpression.java b/src/java/org/apache/poi/sl/draw/geom/LiteralValueExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/LiteralValueExpression.java rename to src/java/org/apache/poi/sl/draw/geom/LiteralValueExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/MaxExpression.java b/src/java/org/apache/poi/sl/draw/geom/MaxExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/MaxExpression.java rename to src/java/org/apache/poi/sl/draw/geom/MaxExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/MinExpression.java b/src/java/org/apache/poi/sl/draw/geom/MinExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/MinExpression.java rename to src/java/org/apache/poi/sl/draw/geom/MinExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/ModExpression.java b/src/java/org/apache/poi/sl/draw/geom/ModExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/ModExpression.java rename to src/java/org/apache/poi/sl/draw/geom/ModExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/MoveToCommand.java b/src/java/org/apache/poi/sl/draw/geom/MoveToCommand.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/MoveToCommand.java rename to src/java/org/apache/poi/sl/draw/geom/MoveToCommand.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/MultiplyDivideExpression.java b/src/java/org/apache/poi/sl/draw/geom/MultiplyDivideExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/MultiplyDivideExpression.java rename to src/java/org/apache/poi/sl/draw/geom/MultiplyDivideExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/Outline.java b/src/java/org/apache/poi/sl/draw/geom/Outline.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/Outline.java rename to src/java/org/apache/poi/sl/draw/geom/Outline.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/Path.java b/src/java/org/apache/poi/sl/draw/geom/Path.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/Path.java rename to src/java/org/apache/poi/sl/draw/geom/Path.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/PathCommand.java b/src/java/org/apache/poi/sl/draw/geom/PathCommand.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/PathCommand.java rename to src/java/org/apache/poi/sl/draw/geom/PathCommand.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/PinExpression.java b/src/java/org/apache/poi/sl/draw/geom/PinExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/PinExpression.java rename to src/java/org/apache/poi/sl/draw/geom/PinExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/PresetGeometries.java b/src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/PresetGeometries.java rename to src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/QuadToCommand.java b/src/java/org/apache/poi/sl/draw/geom/QuadToCommand.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/QuadToCommand.java rename to src/java/org/apache/poi/sl/draw/geom/QuadToCommand.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/SinArcTanExpression.java b/src/java/org/apache/poi/sl/draw/geom/SinArcTanExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/SinArcTanExpression.java rename to src/java/org/apache/poi/sl/draw/geom/SinArcTanExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/SinExpression.java b/src/java/org/apache/poi/sl/draw/geom/SinExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/SinExpression.java rename to src/java/org/apache/poi/sl/draw/geom/SinExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/SqrtExpression.java b/src/java/org/apache/poi/sl/draw/geom/SqrtExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/SqrtExpression.java rename to src/java/org/apache/poi/sl/draw/geom/SqrtExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/TanExpression.java b/src/java/org/apache/poi/sl/draw/geom/TanExpression.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/draw/geom/TanExpression.java rename to src/java/org/apache/poi/sl/draw/geom/TanExpression.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/AutoNumberingScheme.java b/src/java/org/apache/poi/sl/usermodel/AutoNumberingScheme.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/AutoNumberingScheme.java rename to src/java/org/apache/poi/sl/usermodel/AutoNumberingScheme.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/AutoShape.java b/src/java/org/apache/poi/sl/usermodel/AutoShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/AutoShape.java rename to src/java/org/apache/poi/sl/usermodel/AutoShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Background.java b/src/java/org/apache/poi/sl/usermodel/Background.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Background.java rename to src/java/org/apache/poi/sl/usermodel/Background.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/ColorStyle.java b/src/java/org/apache/poi/sl/usermodel/ColorStyle.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/ColorStyle.java rename to src/java/org/apache/poi/sl/usermodel/ColorStyle.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/ConnectorShape.java b/src/java/org/apache/poi/sl/usermodel/ConnectorShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/ConnectorShape.java rename to src/java/org/apache/poi/sl/usermodel/ConnectorShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/FillStyle.java b/src/java/org/apache/poi/sl/usermodel/FillStyle.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/FillStyle.java rename to src/java/org/apache/poi/sl/usermodel/FillStyle.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/FontCollection.java b/src/java/org/apache/poi/sl/usermodel/FontCollection.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/FontCollection.java rename to src/java/org/apache/poi/sl/usermodel/FontCollection.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/FreeformShape.java b/src/java/org/apache/poi/sl/usermodel/FreeformShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/FreeformShape.java rename to src/java/org/apache/poi/sl/usermodel/FreeformShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/GroupShape.java b/src/java/org/apache/poi/sl/usermodel/GroupShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/GroupShape.java rename to src/java/org/apache/poi/sl/usermodel/GroupShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Hyperlink.java b/src/java/org/apache/poi/sl/usermodel/Hyperlink.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Hyperlink.java rename to src/java/org/apache/poi/sl/usermodel/Hyperlink.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Insets2D.java b/src/java/org/apache/poi/sl/usermodel/Insets2D.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Insets2D.java rename to src/java/org/apache/poi/sl/usermodel/Insets2D.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Line.java b/src/java/org/apache/poi/sl/usermodel/Line.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Line.java rename to src/java/org/apache/poi/sl/usermodel/Line.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/LineDecoration.java b/src/java/org/apache/poi/sl/usermodel/LineDecoration.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/LineDecoration.java rename to src/java/org/apache/poi/sl/usermodel/LineDecoration.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/MasterSheet.java b/src/java/org/apache/poi/sl/usermodel/MasterSheet.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/MasterSheet.java rename to src/java/org/apache/poi/sl/usermodel/MasterSheet.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Notes.java b/src/java/org/apache/poi/sl/usermodel/Notes.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Notes.java rename to src/java/org/apache/poi/sl/usermodel/Notes.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/PaintStyle.java b/src/java/org/apache/poi/sl/usermodel/PaintStyle.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/PaintStyle.java rename to src/java/org/apache/poi/sl/usermodel/PaintStyle.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/PictureData.java b/src/java/org/apache/poi/sl/usermodel/PictureData.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/PictureData.java rename to src/java/org/apache/poi/sl/usermodel/PictureData.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/PictureShape.java b/src/java/org/apache/poi/sl/usermodel/PictureShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/PictureShape.java rename to src/java/org/apache/poi/sl/usermodel/PictureShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/PlaceableShape.java b/src/java/org/apache/poi/sl/usermodel/PlaceableShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/PlaceableShape.java rename to src/java/org/apache/poi/sl/usermodel/PlaceableShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Resources.java b/src/java/org/apache/poi/sl/usermodel/Resources.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Resources.java rename to src/java/org/apache/poi/sl/usermodel/Resources.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Shadow.java b/src/java/org/apache/poi/sl/usermodel/Shadow.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Shadow.java rename to src/java/org/apache/poi/sl/usermodel/Shadow.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Shape.java b/src/java/org/apache/poi/sl/usermodel/Shape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Shape.java rename to src/java/org/apache/poi/sl/usermodel/Shape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeContainer.java b/src/java/org/apache/poi/sl/usermodel/ShapeContainer.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeContainer.java rename to src/java/org/apache/poi/sl/usermodel/ShapeContainer.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeType.java b/src/java/org/apache/poi/sl/usermodel/ShapeType.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeType.java rename to src/java/org/apache/poi/sl/usermodel/ShapeType.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Sheet.java b/src/java/org/apache/poi/sl/usermodel/Sheet.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Sheet.java rename to src/java/org/apache/poi/sl/usermodel/Sheet.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/SimpleShape.java b/src/java/org/apache/poi/sl/usermodel/SimpleShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/SimpleShape.java rename to src/java/org/apache/poi/sl/usermodel/SimpleShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Slide.java b/src/java/org/apache/poi/sl/usermodel/Slide.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/Slide.java rename to src/java/org/apache/poi/sl/usermodel/Slide.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/SlideShow.java b/src/java/org/apache/poi/sl/usermodel/SlideShow.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/SlideShow.java rename to src/java/org/apache/poi/sl/usermodel/SlideShow.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/StrokeStyle.java b/src/java/org/apache/poi/sl/usermodel/StrokeStyle.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/StrokeStyle.java rename to src/java/org/apache/poi/sl/usermodel/StrokeStyle.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/TableShape.java b/src/java/org/apache/poi/sl/usermodel/TableShape.java similarity index 92% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/TableShape.java rename to src/java/org/apache/poi/sl/usermodel/TableShape.java index 48744ec38..4fda40f2d 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/TableShape.java +++ b/src/java/org/apache/poi/sl/usermodel/TableShape.java @@ -17,6 +17,6 @@ package org.apache.poi.sl.usermodel; -public interface TableShape extends Shape { +public interface TableShape extends Shape, PlaceableShape { // to be defined ... } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/TextBox.java b/src/java/org/apache/poi/sl/usermodel/TextBox.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/TextBox.java rename to src/java/org/apache/poi/sl/usermodel/TextBox.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/TextParagraph.java b/src/java/org/apache/poi/sl/usermodel/TextParagraph.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/TextParagraph.java rename to src/java/org/apache/poi/sl/usermodel/TextParagraph.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/TextRun.java b/src/java/org/apache/poi/sl/usermodel/TextRun.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/TextRun.java rename to src/java/org/apache/poi/sl/usermodel/TextRun.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/TextShape.java b/src/java/org/apache/poi/sl/usermodel/TextShape.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/TextShape.java rename to src/java/org/apache/poi/sl/usermodel/TextShape.java diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/VerticalAlignment.java b/src/java/org/apache/poi/sl/usermodel/VerticalAlignment.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/sl/usermodel/VerticalAlignment.java rename to src/java/org/apache/poi/sl/usermodel/VerticalAlignment.java diff --git a/src/java/org/apache/poi/ss/formula/FormulaParser.java b/src/java/org/apache/poi/ss/formula/FormulaParser.java index 72ed008cf..5124a4463 100644 --- a/src/java/org/apache/poi/ss/formula/FormulaParser.java +++ b/src/java/org/apache/poi/ss/formula/FormulaParser.java @@ -617,16 +617,16 @@ public final class FormulaParser { return new ParseNode(ptg); } - private static AreaReference createAreaRef(SimpleRangePart part1, SimpleRangePart part2) { + private AreaReference createAreaRef(SimpleRangePart part1, SimpleRangePart part2) { if (!part1.isCompatibleForArea(part2)) { throw new FormulaParseException("has incompatible parts: '" + part1.getRep() + "' and '" + part2.getRep() + "'."); } if (part1.isRow()) { - return AreaReference.getWholeRow(part1.getRep(), part2.getRep()); + return AreaReference.getWholeRow(_ssVersion, part1.getRep(), part2.getRep()); } if (part1.isColumn()) { - return AreaReference.getWholeColumn(part1.getRep(), part2.getRep()); + return AreaReference.getWholeColumn(_ssVersion, part1.getRep(), part2.getRep()); } return new AreaReference(part1.getCellReference(), part2.getCellReference()); } diff --git a/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java b/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java index 5ba894706..cf88b37a6 100644 --- a/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java +++ b/src/java/org/apache/poi/ss/formula/eval/FunctionEval.java @@ -27,8 +27,8 @@ import org.apache.poi.ss.formula.function.FunctionMetadataRegistry; import org.apache.poi.ss.formula.functions.*; /** - * @author Amol S. Deshmukh < amolweb at ya hoo dot com > - * @author Johan Karlsteen - added Intercept and Slope + * Mappings from the Excel functions to our evaluation implementations + * (where avilable) */ public final class FunctionEval { /** @@ -99,7 +99,7 @@ public final class FunctionEval { retval[39] = NumericFunction.MOD; retval[43] = new DStarRunner(new DMin()); - + retval[46] = AggregateFunction.VAR; retval[48] = TextFunction.TEXT; @@ -154,6 +154,7 @@ public final class FunctionEval { retval[124] = TextFunction.FIND; + retval[126] = LogicalFunction.ISERR; retval[127] = LogicalFunction.ISTEXT; retval[128] = LogicalFunction.ISNUMBER; retval[129] = LogicalFunction.ISBLANK; @@ -161,7 +162,7 @@ public final class FunctionEval { retval[FunctionID.INDIRECT] = null; // Indirect.evaluate has different signature - retval[162] = TextFunction.CLEAN; //Aniket Banerjee + retval[162] = TextFunction.CLEAN; retval[167] = new IPMT(); retval[168] = new PPMT(); retval[169] = new Counta(); @@ -177,7 +178,7 @@ public final class FunctionEval { retval[212] = NumericFunction.ROUNDUP; retval[213] = NumericFunction.ROUNDDOWN; retval[216] = new Rank(); - retval[219] = new Address(); //Aniket Banerjee + retval[219] = new Address(); retval[220] = new Days360(); retval[221] = new Today(); @@ -290,7 +291,7 @@ public final class FunctionEval { throw new IllegalArgumentException(name + " is a function from the Excel Analysis Toolpack. " + "Use AnalysisToolpack.registerFunction(String name, FreeRefFunction func) instead."); } - + throw new IllegalArgumentException("Unknown function: " + name); } diff --git a/src/java/org/apache/poi/ss/formula/eval/OperandResolver.java b/src/java/org/apache/poi/ss/formula/eval/OperandResolver.java index 8e0ea3ba8..af4cb81b3 100644 --- a/src/java/org/apache/poi/ss/formula/eval/OperandResolver.java +++ b/src/java/org/apache/poi/ss/formula/eval/OperandResolver.java @@ -57,7 +57,7 @@ public final class OperandResolver { */ public static ValueEval getSingleValue(ValueEval arg, int srcCellRow, int srcCellCol) throws EvaluationException { - ValueEval result; + final ValueEval result; if (arg instanceof RefEval) { result = chooseSingleElementFromRef((RefEval) arg); } else if (arg instanceof AreaEval) { diff --git a/src/java/org/apache/poi/ss/formula/functions/Countif.java b/src/java/org/apache/poi/ss/formula/functions/Countif.java index 6f27fdf48..9023815c3 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Countif.java +++ b/src/java/org/apache/poi/ss/formula/functions/Countif.java @@ -30,7 +30,7 @@ import org.apache.poi.ss.formula.eval.RefEval; import org.apache.poi.ss.formula.eval.StringEval; import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.functions.CountUtils.I_MatchPredicate; -import org.apache.poi.ss.usermodel.ErrorConstants; +import org.apache.poi.ss.usermodel.FormulaError; /** * Implementation for the function COUNTIF @@ -254,6 +254,7 @@ public final class Countif extends Fixed2ArgFunction { // boolean values when the target(x) is a string return false; } + @SuppressWarnings("unused") StringEval se = (StringEval)x; Boolean val = parseBoolean(se.getStringValue()); if(val == null) { @@ -286,7 +287,7 @@ public final class Countif extends Fixed2ArgFunction { return evaluate(testValue - _value); } } - private static final class ErrorMatcher extends MatcherBase { + public static final class ErrorMatcher extends MatcherBase { private final int _value; @@ -296,7 +297,7 @@ public final class Countif extends Fixed2ArgFunction { } @Override protected String getValueText() { - return ErrorConstants.getText(_value); + return FormulaError.forInt(_value).getString(); } public boolean matches(ValueEval x) { @@ -306,6 +307,10 @@ public final class Countif extends Fixed2ArgFunction { } return false; } + + public int getValue() { + return _value; + } } public static final class StringMatcher extends MatcherBase { @@ -486,7 +491,7 @@ public final class Countif extends Fixed2ArgFunction { */ private static ValueEval evaluateCriteriaArg(ValueEval arg, int srcRowIndex, int srcColumnIndex) { try { - return OperandResolver.getSingleValue(arg, srcRowIndex, (short)srcColumnIndex); + return OperandResolver.getSingleValue(arg, srcRowIndex, srcColumnIndex); } catch (EvaluationException e) { return e.getErrorEval(); } diff --git a/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java b/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java index ef18dab64..c4b3e6718 100644 --- a/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java +++ b/src/java/org/apache/poi/ss/formula/functions/LogicalFunction.java @@ -90,6 +90,27 @@ public abstract class LogicalFunction extends Fixed1ArgFunction { } }; + /** + * Implementation of Excel ISERR() function.

    + * + * Syntax:
    + * ISERR(value)

    + * + * value The value to be tested

    + * + * Returns the logical value TRUE if value refers to any error value except + * '#N/A'; otherwise, it returns FALSE. + */ + public static final Function ISERR = new LogicalFunction() { + @Override + protected boolean evaluate(ValueEval arg) { + if (arg instanceof ErrorEval) { + return arg != ErrorEval.NA; + } + return false; + } + }; + /** * Implementation for Excel ISNA() function.

    * diff --git a/src/java/org/apache/poi/ss/formula/functions/Sumif.java b/src/java/org/apache/poi/ss/formula/functions/Sumif.java index ef381adb0..977647fd2 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Sumif.java +++ b/src/java/org/apache/poi/ss/formula/functions/Sumif.java @@ -69,6 +69,12 @@ public final class Sumif extends Var2or3ArgFunction { AreaEval aeSum) { // TODO - junit to prove last arg must be srcColumnIndex and not srcRowIndex I_MatchPredicate mp = Countif.createCriteriaPredicate(arg1, srcRowIndex, srcColumnIndex); + + // handle empty cells + if(mp == null) { + return NumberEval.ZERO; + } + double result = sumMatchingCells(aeRange, mp, aeSum); return new NumberEval(result); } diff --git a/src/java/org/apache/poi/ss/formula/functions/Sumifs.java b/src/java/org/apache/poi/ss/formula/functions/Sumifs.java index 63d35439a..ebdddb69f 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Sumifs.java +++ b/src/java/org/apache/poi/ss/formula/functions/Sumifs.java @@ -20,8 +20,14 @@ package org.apache.poi.ss.formula.functions; import org.apache.poi.ss.formula.OperationEvaluationContext; -import org.apache.poi.ss.formula.eval.*; +import org.apache.poi.ss.formula.eval.AreaEval; +import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.ss.formula.eval.EvaluationException; +import org.apache.poi.ss.formula.eval.NumberEval; +import org.apache.poi.ss.formula.eval.RefEval; +import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.functions.CountUtils.I_MatchPredicate; +import org.apache.poi.ss.formula.functions.Countif.ErrorMatcher; /** * Implementation for the Excel function SUMIFS

    @@ -48,6 +54,7 @@ public final class Sumifs implements FreeRefFunction { public static final FreeRefFunction instance = new Sumifs(); public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { + // need at least 3 arguments and need to have an odd number of arguments (sum-range plus x*(criteria_range, criteria)) if(args.length < 3 || args.length % 2 == 0) { return ErrorEval.VALUE_INVALID; } @@ -60,10 +67,12 @@ public final class Sumifs implements FreeRefFunction { I_MatchPredicate[] mp = new I_MatchPredicate[ae.length]; for(int i = 1, k=0; i < args.length; i += 2, k++){ ae[k] = convertRangeArg(args[i]); + mp[k] = Countif.createCriteriaPredicate(args[i+1], ec.getRowIndex(), ec.getColumnIndex()); } validateCriteriaRanges(ae, sumRange); + validateCriteria(mp); double result = sumMatchingCells(ae, mp, sumRange); return new NumberEval(result); @@ -76,7 +85,7 @@ public final class Sumifs implements FreeRefFunction { * Verify that each criteriaRanges argument contains the same number of rows and columns * as the sumRange argument * - * @throws EvaluationException if + * @throws EvaluationException if the ranges do not match. */ private void validateCriteriaRanges(AreaEval[] criteriaRanges, AreaEval sumRange) throws EvaluationException { for(AreaEval r : criteriaRanges){ @@ -87,6 +96,22 @@ public final class Sumifs implements FreeRefFunction { } } + /** + * Verify that each criteria predicate is valid, i.e. not an error + * + * @throws EvaluationException if there are criteria which resulted in Errors. + */ + private void validateCriteria(I_MatchPredicate[] criteria) throws EvaluationException { + for(I_MatchPredicate predicate : criteria) { + + // check for errors in predicate and return immediately using this error code + if(predicate instanceof ErrorMatcher) { + throw new EvaluationException(ErrorEval.valueOf(((ErrorMatcher)predicate).getValue())); + } + } + } + + /** * * @param ranges criteria ranges, each range must be of the same dimensions as aeSum diff --git a/src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java b/src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java index e27ccdd7a..665ac98cf 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java @@ -31,7 +31,7 @@ import org.apache.poi.util.LittleEndianOutput; *

    This is XSSF only, as it stores the sheet / book references * in String form. The HSSF equivalent using indexes is {@link Area3DPtg}

    */ -public final class Area3DPxg extends AreaPtgBase implements Pxg { +public final class Area3DPxg extends AreaPtgBase implements Pxg3D { private int externalWorkbookNumber = -1; private String firstSheetName; private String lastSheetName; diff --git a/src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java b/src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java index 5b77b09fe..96eda8757 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java +++ b/src/java/org/apache/poi/ss/formula/ptg/AreaPtgBase.java @@ -17,6 +17,7 @@ package org.apache.poi.ss.formula.ptg; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.BitField; @@ -256,7 +257,7 @@ public abstract class AreaPtgBase extends OperandPtg implements AreaI { CellReference topLeft = new CellReference(getFirstRow(),getFirstColumn(),!isFirstRowRelative(),!isFirstColRelative()); CellReference botRight = new CellReference(getLastRow(),getLastColumn(),!isLastRowRelative(),!isLastColRelative()); - if(AreaReference.isWholeColumnReference(topLeft, botRight)) { + if(AreaReference.isWholeColumnReference(SpreadsheetVersion.EXCEL97, topLeft, botRight)) { return (new AreaReference(topLeft, botRight)).formatAsString(); } return topLeft.formatAsString() + ":" + botRight.formatAsString(); diff --git a/src/java/org/apache/poi/ss/formula/ptg/Pxg3D.java b/src/java/org/apache/poi/ss/formula/ptg/Pxg3D.java new file mode 100644 index 000000000..49083fe15 --- /dev/null +++ b/src/java/org/apache/poi/ss/formula/ptg/Pxg3D.java @@ -0,0 +1,27 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.ptg; + +/** + * An XSSF only special kind of Ptg, which stores a range of + * sheet / book references in string form. + */ +public interface Pxg3D extends Pxg { + public String getLastSheetName(); + public void setLastSheetName(String sheetName); +} diff --git a/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java b/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java index 41039cd92..3b78c5a4b 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java +++ b/src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java @@ -31,7 +31,7 @@ import org.apache.poi.util.LittleEndianOutput; *

    This is XSSF only, as it stores the sheet / book references * in String form. The HSSF equivalent using indexes is {@link Ref3DPtg}

    */ -public final class Ref3DPxg extends RefPtgBase implements Pxg { +public final class Ref3DPxg extends RefPtgBase implements Pxg3D { private int externalWorkbookNumber = -1; private String firstSheetName; private String lastSheetName; diff --git a/src/java/org/apache/poi/ss/usermodel/BorderFormatting.java b/src/java/org/apache/poi/ss/usermodel/BorderFormatting.java index c15dc269c..165cf0542 100644 --- a/src/java/org/apache/poi/ss/usermodel/BorderFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/BorderFormatting.java @@ -20,8 +20,8 @@ package org.apache.poi.ss.usermodel; /** - * @author Dmitriy Kumshayev - * @author Yegor Kozlov + * High level representation for Border Formatting component + * of Conditional Formatting settings */ public interface BorderFormatting { /** No border */ @@ -64,14 +64,19 @@ public interface BorderFormatting { short getBorderTop(); short getBottomBorderColor(); + Color getBottomBorderColorColor(); short getDiagonalBorderColor(); + Color getDiagonalBorderColorColor(); short getLeftBorderColor(); + Color getLeftBorderColorColor(); short getRightBorderColor(); + Color getRightBorderColorColor(); short getTopBorderColor(); + Color getTopBorderColorColor(); void setBorderBottom(short border); @@ -104,12 +109,17 @@ public interface BorderFormatting { void setBorderTop(short border); void setBottomBorderColor(short color); + void setBottomBorderColor(Color color); void setDiagonalBorderColor(short color); + void setDiagonalBorderColor(Color color); void setLeftBorderColor(short color); + void setLeftBorderColor(Color color); void setRightBorderColor(short color); + void setRightBorderColor(Color color); void setTopBorderColor(short color); + void setTopBorderColor(Color color); } diff --git a/src/java/org/apache/poi/ss/usermodel/ColorScaleFormatting.java b/src/java/org/apache/poi/ss/usermodel/ColorScaleFormatting.java new file mode 100644 index 000000000..4d6f58b58 --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/ColorScaleFormatting.java @@ -0,0 +1,66 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +import org.apache.poi.hssf.record.cf.Threshold; + +/** + * High level representation for the Color Scale / Colour Scale / + * Color Gradient Formatting component of Conditional Formatting settings + */ +public interface ColorScaleFormatting { + /** + * How many control points should be used to map + * the colours? Normally 2 or 3 + */ + int getNumControlPoints(); + /** + * Sets the number of control points to use to map + * the colours. Should normally be 2 or 3. + *

    After updating, you need to ensure that the + * {@link Threshold} count and Color count match + */ + void setNumControlPoints(int num); + + /** + * Gets the list of colours that are interpolated + * between. + */ + Color[] getColors(); + /** + * Sets the list of colours that are interpolated + * between. The number must match {@link #getNumControlPoints()} + */ + void setColors(Color[] colors); + + /** + * Gets the list of thresholds + */ + ConditionalFormattingThreshold[] getThresholds(); + /** + * Sets the of thresholds. The number must match + * {@link #getNumControlPoints()} + */ + void setThresholds(ConditionalFormattingThreshold[] thresholds); + /** + * Creates a new, empty Threshold + */ + ConditionalFormattingThreshold createThreshold(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/ComparisonOperator.java b/src/java/org/apache/poi/ss/usermodel/ComparisonOperator.java index 7e29cbf4c..7eee78903 100644 --- a/src/java/org/apache/poi/ss/usermodel/ComparisonOperator.java +++ b/src/java/org/apache/poi/ss/usermodel/ComparisonOperator.java @@ -24,9 +24,6 @@ package org.apache.poi.ss.usermodel; *

    * For example, "highlight cells that begin with "M2" and contain "Mountain Gear". *

    - * - * @author Dmitriy Kumshayev - * @author Yegor Kozlov */ public final class ComparisonOperator { public static final byte NO_COMPARISON = 0; diff --git a/src/java/org/apache/poi/ss/usermodel/ConditionType.java b/src/java/org/apache/poi/ss/usermodel/ConditionType.java new file mode 100644 index 000000000..8bd61410e --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/ConditionType.java @@ -0,0 +1,92 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +import java.util.HashMap; +import java.util.Map; + +/** + * Represents a type of a conditional formatting rule + */ +public class ConditionType { + private static Map lookup = new HashMap(); + + /** + * This conditional formatting rule compares a cell value + * to a formula calculated result, using an operator + */ + public static final ConditionType CELL_VALUE_IS = + new ConditionType(1, "cellIs"); + + /** + * This conditional formatting rule contains a formula to evaluate. + * When the formula result is true, the cell is highlighted. + */ + public static final ConditionType FORMULA = + new ConditionType(2, "expression"); + + /** + * This conditional formatting rule contains a color scale, + * with the cell background set according to a gradient. + */ + public static final ConditionType COLOR_SCALE = + new ConditionType(3, "colorScale"); + + /** + * This conditional formatting rule sets a data bar, with the + * cell populated with bars based on their values + */ + public static final ConditionType DATA_BAR = + new ConditionType(4, "dataBar"); + + /** + * This conditional formatting rule that files the values + */ + public static final ConditionType FILTER = + new ConditionType(5, null); + + /** + * This conditional formatting rule sets a data bar, with the + * cell populated with bars based on their values + */ + public static final ConditionType ICON_SET = + new ConditionType(6, "iconSet"); + + + public final byte id; + public final String type; + + public String toString() { + return id + " - " + type; + } + + + public static ConditionType forId(byte id) { + return forId((int)id); + } + public static ConditionType forId(int id) { + return lookup.get(id); + } + + private ConditionType(int id, String type) { + this.id = (byte)id; this.type = type; + lookup.put(id, this); + } +} diff --git a/src/java/org/apache/poi/ss/usermodel/ConditionalFormatting.java b/src/java/org/apache/poi/ss/usermodel/ConditionalFormatting.java index 3344963bb..f6e8ff441 100644 --- a/src/java/org/apache/poi/ss/usermodel/ConditionalFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/ConditionalFormatting.java @@ -72,9 +72,6 @@ import org.apache.poi.ss.util.CellRangeAddress; * // Apply Conditional Formatting rule defined above to the regions * sheet.addConditionalFormatting(regions, rule); * - * - * @author Dmitriy Kumshayev - * @author Yegor Kozlov */ public interface ConditionalFormatting { @@ -85,17 +82,18 @@ public interface ConditionalFormatting { /** * Replaces an existing Conditional Formatting rule at position idx. - * Excel allows to create up to 3 Conditional Formatting rules. + * Excel pre-2007 allows to create up to 3 Conditional Formatting rules, + * 2007 and later allow unlimited numbers. * This method can be useful to modify existing Conditional Formatting rules. * - * @param idx position of the rule. Should be between 0 and 2. + * @param idx position of the rule. Should be between 0 and 2 for Excel before 2007, otherwise 0+. * @param cfRule - Conditional Formatting rule */ void setRule(int idx, ConditionalFormattingRule cfRule); /** * Add a Conditional Formatting rule. - * Excel allows to create up to 3 Conditional Formatting rules. + * Excel pre-2007 allows to create up to 3 Conditional Formatting rules. * * @param cfRule - Conditional Formatting rule */ @@ -110,6 +108,4 @@ public interface ConditionalFormatting { * @return number of Conditional Formatting rules. */ int getNumberOfRules(); - - } diff --git a/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingRule.java b/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingRule.java index 1c63f1925..5fb315147 100644 --- a/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingRule.java +++ b/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingRule.java @@ -19,24 +19,25 @@ package org.apache.poi.ss.usermodel; +import static org.apache.poi.ss.usermodel.ConditionType.*; + /** * Represents a description of a conditional formatting rule - * - * @author Dmitriy Kumshayev - * @author Yegor Kozlov */ public interface ConditionalFormattingRule { /** * This conditional formatting rule compares a cell value * to a formula calculated result, using an operator + * @deprecated Use {@link ConditionType#CELL_VALUE_IS} */ - public static final byte CONDITION_TYPE_CELL_VALUE_IS = 1; + public static final byte CONDITION_TYPE_CELL_VALUE_IS = CELL_VALUE_IS.id; /** * This conditional formatting rule contains a formula to evaluate. * When the formula result is true, the cell is highlighted. + * @deprecated Use {@link ConditionType#FORMULA} */ - public static final byte CONDITION_TYPE_FORMULA = 2; + public static final byte CONDITION_TYPE_FORMULA = FORMULA.id; /** * Create a new border formatting structure if it does not exist, @@ -73,19 +74,32 @@ public interface ConditionalFormattingRule { PatternFormatting createPatternFormatting(); /** - * @return - pattern formatting object if defined, null otherwise + * @return - pattern formatting object if defined, null otherwise */ PatternFormatting getPatternFormatting(); + /** + * @return - icon / multi-state formatting object if defined, null otherwise + */ + IconMultiStateFormatting getMultiStateFormatting(); + /** * Type of conditional formatting rule. *

    - * MUST be either {@link #CONDITION_TYPE_CELL_VALUE_IS} or {@link #CONDITION_TYPE_FORMULA} + * MUST be one of the IDs of a {@link ConditionType} *

    * * @return the type of condition + * @deprecated Use {@link #getConditionTypeType()} */ byte getConditionType(); + + /** + * Type of conditional formatting rule. + * + * @return the type of condition + */ + ConditionType getConditionTypeType(); /** * The comparison function used when the type of conditional formatting is set to diff --git a/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingThreshold.java b/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingThreshold.java new file mode 100644 index 000000000..8f2ecaf52 --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/ConditionalFormattingThreshold.java @@ -0,0 +1,110 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + + +/** + * The Threshold / CFVO / Conditional Formatting Value Object. + *

    This defines how to calculate the ranges for a conditional + * formatting rule, eg which values get a Green Traffic Light + * icon and which Yellow or Red.

    + */ +public interface ConditionalFormattingThreshold { + public enum RangeType { + /** Number / Parameter */ + NUMBER(1, "num"), + /** The minimum value from the range */ + MIN(2, "min"), + /** The maximum value from the range */ + MAX(3, "max"), + /** Percent of the way from the mi to the max value in the range */ + PERCENT(4, "percent"), + /** The minimum value of the cell that is in X percentile of the range */ + PERCENTILE(5, "percentile"), + UNALLOCATED(6, null), + /** Formula result */ + FORMULA(7, "formula"); + + /** Numeric ID of the type */ + public int id; + /** Name (system) of the type */ + public final String name; + + public String toString() { + return id + " - " + name; + } + + public static RangeType byId(int id) { + return values()[id-1]; // 1-based IDs + } + public static RangeType byName(String name) { + for (RangeType t : values()) { + if (t.name.equals(name)) return t; + } + return null; + } + + private RangeType(int id, String name) { + this.id = id; this.name = name; + } + } + + /** + * Get the Range Type used + */ + RangeType getRangeType(); + + /** + * Changes the Range Type used + * + *

    If you change the range type, you need to + * ensure that the Formula and Value parameters + * are compatible with it before saving

    + */ + void setRangeType(RangeType type); + + /** + * Formula to use to calculate the threshold, + * or null if no formula + */ + String getFormula(); + + /** + * Sets the formula used to calculate the threshold, + * or unsets it if null is given. + */ + void setFormula(String formula); + + /** + * Gets the value used for the threshold, or + * null if there isn't one. + */ + Double getValue(); + + /** + * Sets the value used for the threshold. + *

    If the type is {@link RangeType#PERCENT} or + * {@link RangeType#PERCENTILE} it must be between 0 and 100. + *

    If the type is {@link RangeType#MIN} or {@link RangeType#MAX} + * or {@link RangeType#FORMULA} it shouldn't be set. + *

    Use null to unset + */ + void setValue(Double value); +} diff --git a/src/java/org/apache/poi/ss/usermodel/DataBarFormatting.java b/src/java/org/apache/poi/ss/usermodel/DataBarFormatting.java new file mode 100644 index 000000000..df9a0fef7 --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/DataBarFormatting.java @@ -0,0 +1,72 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +/** + * High level representation for the DataBar Formatting + * component of Conditional Formatting settings + */ +public interface DataBarFormatting { + /** + * Is the bar drawn from Left-to-Right, or from + * Right-to-Left + */ + boolean isLeftToRight(); + /** + * Control if the bar is drawn from Left-to-Right, + * or from Right-to-Left + */ + void setLeftToRight(boolean ltr); + + /** + * Should Icon + Value be displayed, or only the Icon? + */ + boolean isIconOnly(); + /** + * Control if only the Icon is shown, or Icon + Value + */ + void setIconOnly(boolean only); + + /** + * How much of the cell width, in %, should be given to + * the min value? + */ + int getWidthMin(); + void setWidthMin(int width); + + /** + * How much of the cell width, in %, should be given to + * the max value? + */ + int getWidthMax(); + void setWidthMax(int width); + + Color getColor(); + void setColor(Color color); + + /** + * The threshold that defines "everything from here down is minimum" + */ + ConditionalFormattingThreshold getMinThreshold(); + /** + * The threshold that defines "everything from here up is maximum" + */ + ConditionalFormattingThreshold getMaxThreshold(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java index 28dbfbe3f..766ded18f 100644 --- a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java +++ b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java @@ -20,6 +20,7 @@ ==================================================================== */ package org.apache.poi.ss.usermodel; +import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DateFormatSymbols; import java.text.DecimalFormat; @@ -38,6 +39,8 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.poi.ss.util.NumberToTextConverter; + /** * DataFormatter contains methods for formatting the value stored in an @@ -731,7 +734,7 @@ public class DataFormatter { * @see #formatCellValue(Cell) */ public String formatRawCellContents(double value, int formatIndex, String formatString) { - return formatRawCellContents(value, formatIndex, formatString, false); + return formatRawCellContents(value, formatIndex, formatString, false); } /** * Formats the given raw cell value, based on the supplied @@ -744,28 +747,42 @@ public class DataFormatter { if(DateUtil.isValidExcelDate(value)) { Format dateFormat = getFormat(value, formatIndex, formatString); if(dateFormat instanceof ExcelStyleDateFormatter) { - // Hint about the raw excel value - ((ExcelStyleDateFormatter)dateFormat).setDateToBeFormatted(value); + // Hint about the raw excel value + ((ExcelStyleDateFormatter)dateFormat).setDateToBeFormatted(value); } Date d = DateUtil.getJavaDate(value, use1904Windowing); return performDateFormatting(d, dateFormat); } - // RK: Invalid dates are 255 #s. - if (emulateCsv) { - return invalidDateTimeString; - } + // RK: Invalid dates are 255 #s. + if (emulateCsv) { + return invalidDateTimeString; + } } + // else Number - Format numberFormat = getFormat(value, formatIndex, formatString); - if (numberFormat == null) { - return String.valueOf(value); - } - // RK: This hack handles scientific notation by adding the missing + back. - String result = numberFormat.format(new Double(value)); - if (result.contains("E") && !result.contains("E-")) { - result = result.replaceFirst("E", "E+"); - } - return result; + Format numberFormat = getFormat(value, formatIndex, formatString); + if (numberFormat == null) { + return String.valueOf(value); + } + + // When formatting 'value', double to text to BigDecimal produces more + // accurate results than double to Double in JDK8 (as compared to + // previous versions). However, if the value contains E notation, this + // would expand the values, which we do not want, so revert to + // original method. + String result; + final String textValue = NumberToTextConverter.toText(value); + if (textValue.indexOf('E') > -1) { + result = numberFormat.format(new Double(value)); + } + else { + result = numberFormat.format(new BigDecimal(textValue)); + } + // Complete scientific notation by adding the missing +. + if (result.indexOf('E') > -1 && !result.contains("E-")) { + result = result.replaceFirst("E", "E+"); + } + return result; } /** diff --git a/src/java/org/apache/poi/ss/usermodel/DateUtil.java b/src/java/org/apache/poi/ss/usermodel/DateUtil.java index 79512ef10..ca1d7d465 100644 --- a/src/java/org/apache/poi/ss/usermodel/DateUtil.java +++ b/src/java/org/apache/poi/ss/usermodel/DateUtil.java @@ -146,7 +146,7 @@ public class DateUtil { * @return Java representation of the date, or null if date is not a valid Excel date */ public static Date getJavaDate(double date, TimeZone tz) { - return getJavaDate(date, false, tz); + return getJavaDate(date, false, tz, false); } /** * Given an Excel date with using 1900 date windowing, and @@ -166,9 +166,9 @@ public class DateUtil { * @see java.util.TimeZone */ public static Date getJavaDate(double date) { - return getJavaDate(date, (TimeZone)null); + return getJavaDate(date, false, null, false); } - + /** * Given an Excel date with either 1900 or 1904 date windowing, * converts it to a java.util.Date. @@ -185,7 +185,7 @@ public class DateUtil { * @return Java representation of the date, or null if date is not a valid Excel date */ public static Date getJavaDate(double date, boolean use1904windowing, TimeZone tz) { - return getJavaCalendar(date, use1904windowing, tz, false).getTime(); + return getJavaDate(date, use1904windowing, tz, false); } /** @@ -205,7 +205,8 @@ public class DateUtil { * @return Java representation of the date, or null if date is not a valid Excel date */ public static Date getJavaDate(double date, boolean use1904windowing, TimeZone tz, boolean roundSeconds) { - return getJavaCalendar(date, use1904windowing, tz, roundSeconds).getTime(); + Calendar calendar = getJavaCalendar(date, use1904windowing, tz, roundSeconds); + return calendar == null ? null : calendar.getTime(); } /** @@ -228,10 +229,9 @@ public class DateUtil { * @see java.util.TimeZone */ public static Date getJavaDate(double date, boolean use1904windowing) { - return getJavaCalendar(date, use1904windowing, null, false).getTime(); + return getJavaDate(date, use1904windowing, null, false); } - public static void setCalendar(Calendar calendar, int wholeDays, int millisecondsInDay, boolean use1904windowing, boolean roundSeconds) { int startYear = 1900; @@ -567,7 +567,7 @@ public class DateUtil { private static int daysInPriorYears(int yr, boolean use1904windowing) { - if ((!use1904windowing && yr < 1900) || (use1904windowing && yr < 1900)) { + if ((!use1904windowing && yr < 1900) || (use1904windowing && yr < 1904)) { throw new IllegalArgumentException("'year' must be 1900 or greater"); } diff --git a/src/java/org/apache/poi/ss/usermodel/FontFormatting.java b/src/java/org/apache/poi/ss/usermodel/FontFormatting.java index 2298d7963..a6f21bde4 100644 --- a/src/java/org/apache/poi/ss/usermodel/FontFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/FontFormatting.java @@ -22,9 +22,6 @@ package org.apache.poi.ss.usermodel; /** * High level representation for Font Formatting component * of Conditional Formatting settings - * - * @author Dmitriy Kumshayev - * @author Yegor Kozlov */ public interface FontFormatting { /** Escapement type - None */ @@ -66,15 +63,26 @@ public interface FontFormatting { void setEscapementType(short escapementType); /** - * @return font color index + * @return font colour index, or 0 if not indexed (XSSF only) */ short getFontColorIndex(); - /** - * @param color font color index + * Sets the indexed colour to use + * @param color font colour index */ void setFontColorIndex(short color); + + /** + * @return The colour of the font, or null if no colour applied + */ + Color getFontColor(); + + /** + * Sets the colour to use + * @param color font colour to use + */ + void setFontColor(Color color); /** * gets the height of the font in 1/20th point units diff --git a/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java b/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java new file mode 100644 index 000000000..d5212e5b9 --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/IconMultiStateFormatting.java @@ -0,0 +1,127 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.ss.usermodel; + +/** + * High level representation for the Icon / Multi-State Formatting + * component of Conditional Formatting settings + */ +public interface IconMultiStateFormatting { + public enum IconSet { + /** Green Up / Yellow Side / Red Down arrows */ + GYR_3_ARROW(0, 3, "3Arrows"), + /** Grey Up / Side / Down arrows */ + GREY_3_ARROWS(1, 3, "3ArrowsGray"), + /** Green / Yellow / Red flags */ + GYR_3_FLAGS(2, 3, "3Flags"), + /** Green / Yellow / Red traffic lights (no background). Default */ + GYR_3_TRAFFIC_LIGHTS(3, 3, "3TrafficLights1"), + /** Green / Yellow / Red traffic lights on a black square background. + * Note, MS-XLS docs v20141018 say this is id=5 but seems to be id=4 */ + GYR_3_TRAFFIC_LIGHTS_BOX(4, 3, "3TrafficLights2"), + /** Green Circle / Yellow Triangle / Red Diamond. + * Note, MS-XLS docs v20141018 say this is id=4 but seems to be id=5 */ + GYR_3_SHAPES(5, 3, "3Signs"), + /** Green Tick / Yellow ! / Red Cross on a circle background */ + GYR_3_SYMBOLS_CIRCLE(6, 3, "3Symbols"), + /** Green Tick / Yellow ! / Red Cross (no background) */ + GYR_3_SYMBOLS(7, 3, "3Symbols2"), + /** Green Up / Yellow NE / Yellow SE / Red Down arrows */ + GYR_4_ARROWS(8, 4, "4Arrows"), + /** Grey Up / NE / SE / Down arrows */ + GREY_4_ARROWS(9, 4, "4ArrowsGray"), + /** Red / Light Red / Grey / Black traffic lights */ + RB_4_TRAFFIC_LIGHTS(0xA, 4, "4RedToBlack"), + RATINGS_4(0xB, 4, "4Rating"), + /** Green / Yellow / Red / Black traffic lights */ + GYRB_4_TRAFFIC_LIGHTS(0xC, 4, "4TrafficLights"), + GYYYR_5_ARROWS(0xD, 5, "5Arrows"), + GREY_5_ARROWS(0xE, 5, "5ArrowsGray"), + RATINGS_5(0xF, 5, "5Rating"), + QUARTERS_5(0x10, 5, "5Quarters"); + + protected static final IconSet DEFAULT_ICONSET = IconSet.GYR_3_TRAFFIC_LIGHTS; + + /** Numeric ID of the icon set */ + public int id; + /** How many icons in the set */ + public final int num; + /** Name (system) of the set */ + public final String name; + + public String toString() { + return id + " - " + name; + } + + public static IconSet byId(int id) { + return values()[id]; + } + public static IconSet byName(String name) { + for (IconSet set : values()) { + if (set.name.equals(name)) return set; + } + return null; + } + + private IconSet(int id, int num, String name) { + this.id = id; this.num = num; this.name = name; + } + } + + /** + * Get the Icon Set used + */ + IconSet getIconSet(); + + /** + * Changes the Icon Set used + * + *

    If the new Icon Set has a different number of + * icons to the old one, you must update the + * thresholds before saving!

    + */ + void setIconSet(IconSet set); + + /** + * Should Icon + Value be displayed, or only the Icon? + */ + boolean isIconOnly(); + /** + * Control if only the Icon is shown, or Icon + Value + */ + void setIconOnly(boolean only); + + boolean isReversed(); + void setReversed(boolean reversed); + + /** + * Gets the list of thresholds + */ + ConditionalFormattingThreshold[] getThresholds(); + /** + * Sets the of thresholds. The number must match + * {@link IconSet#num} for the current {@link #getIconSet()} + */ + void setThresholds(ConditionalFormattingThreshold[] thresholds); + /** + * Creates a new, empty Threshold + */ + ConditionalFormattingThreshold createThreshold(); +} diff --git a/src/java/org/apache/poi/ss/usermodel/PatternFormatting.java b/src/java/org/apache/poi/ss/usermodel/PatternFormatting.java index 2739c96af..0311ffb75 100644 --- a/src/java/org/apache/poi/ss/usermodel/PatternFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/PatternFormatting.java @@ -63,14 +63,16 @@ public interface PatternFormatting { public final static short LEAST_DOTS = 18 ; short getFillBackgroundColor(); - short getFillForegroundColor(); + Color getFillBackgroundColorColor(); + Color getFillForegroundColorColor(); short getFillPattern(); void setFillBackgroundColor(short bg); - void setFillForegroundColor(short fg); + void setFillBackgroundColor(Color bg); + void setFillForegroundColor(Color fg); void setFillPattern(short fp); } diff --git a/src/java/org/apache/poi/ss/usermodel/Sheet.java b/src/java/org/apache/poi/ss/usermodel/Sheet.java index 987a35efe..f0990511f 100644 --- a/src/java/org/apache/poi/ss/usermodel/Sheet.java +++ b/src/java/org/apache/poi/ss/usermodel/Sheet.java @@ -320,6 +320,13 @@ public interface Sheet extends Iterable { */ public CellRangeAddress getMergedRegion(int index); + /** + * Returns the list of merged regions. + * + * @return the list of merged regions + */ + public List getMergedRegions(); + /** * Returns an iterator of the physical rows * diff --git a/src/java/org/apache/poi/ss/usermodel/SheetConditionalFormatting.java b/src/java/org/apache/poi/ss/usermodel/SheetConditionalFormatting.java index e20a8f74b..a28c342a7 100644 --- a/src/java/org/apache/poi/ss/usermodel/SheetConditionalFormatting.java +++ b/src/java/org/apache/poi/ss/usermodel/SheetConditionalFormatting.java @@ -19,17 +19,15 @@ package org.apache.poi.ss.usermodel; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.util.CellRangeAddress; /** * The 'Conditional Formatting' facet of Sheet * - * @author Dmitriy Kumshayev - * @author Yegor Kozlov * @since 3.8 */ public interface SheetConditionalFormatting { - /** * Add a new Conditional Formatting to the sheet. * @@ -58,7 +56,7 @@ public interface SheetConditionalFormatting { * Add a new Conditional Formatting set to the sheet. * * @param regions - list of rectangular regions to apply conditional formatting rules - * @param cfRules - set of up to three conditional formatting rules + * @param cfRules - set of up to conditional formatting rules (max 3 for Excel pre-2007) * * @return index of the newly created Conditional Formatting object */ @@ -86,7 +84,7 @@ public interface SheetConditionalFormatting { *

    * The created conditional formatting rule compares a cell value * to a formula calculated result, using the specified operator. - * The type of the created condition is {@link ConditionalFormattingRule#CONDITION_TYPE_CELL_VALUE_IS} + * The type of the created condition is {@link ConditionType#CELL_VALUE_IS} *

    * * @param comparisonOperation - MUST be a constant value from @@ -115,7 +113,7 @@ public interface SheetConditionalFormatting { * Create a conditional formatting rule that compares a cell value * to a formula calculated result, using an operator * *

    - * The type of the created condition is {@link ConditionalFormattingRule#CONDITION_TYPE_CELL_VALUE_IS} + * The type of the created condition is {@link ConditionType#CELL_VALUE_IS} *

    * * @param comparisonOperation MUST be a constant value from @@ -132,12 +130,24 @@ public interface SheetConditionalFormatting { * When the formula result is true, the cell is highlighted. * *

    - * The type of the created format condition is {@link ConditionalFormattingRule#CONDITION_TYPE_FORMULA} + * The type of the created format condition is {@link ConditionType#FORMULA} *

    * @param formula the formula to evaluate. MUST be a Boolean function. */ ConditionalFormattingRule createConditionalFormattingRule(String formula); + /** + * Create an Icon Set / Multi-State conditional formatting rule. + *

    The thresholds for it will be created, but will be empty + * and require configuring with + * {@link ConditionalFormattingRule#getMultiStateFormatting()} + * then + * {@link IconMultiStateFormatting#getThresholds()} + */ + ConditionalFormattingRule createConditionalFormattingRule(IconSet iconSet); + + // TODO Support types beyond CELL_VALUE_IS and FORMULA and ICONs + /** * Gets Conditional Formatting object at a particular index * diff --git a/src/java/org/apache/poi/ss/util/AreaReference.java b/src/java/org/apache/poi/ss/util/AreaReference.java index d59388873..b0a69135a 100644 --- a/src/java/org/apache/poi/ss/util/AreaReference.java +++ b/src/java/org/apache/poi/ss/util/AreaReference.java @@ -35,13 +35,23 @@ public class AreaReference { private final CellReference _firstCell; private final CellReference _lastCell; private final boolean _isSingleCell; + private SpreadsheetVersion _version; + /** + * @deprecated Prefer supplying a version. + */ + @Deprecated + public AreaReference(String reference) { + this(reference, SpreadsheetVersion.EXCEL97); + } + /** * Create an area ref from a string representation. Sheet names containing special characters should be * delimited and escaped as per normal syntax rules for formulas.
    * The area reference must be contiguous (i.e. represent a single rectangle, not a union of rectangles) */ - public AreaReference(String reference) { + public AreaReference(String reference, SpreadsheetVersion version) { + _version = version; if(! isContiguous(reference)) { throw new IllegalArgumentException( "References passed to the AreaReference must be contiguous, " + @@ -169,30 +179,34 @@ public class AreaReference { return false; } - public static AreaReference getWholeRow(String start, String end) { - return new AreaReference("$A" + start + ":$IV" + end); + public static AreaReference getWholeRow(SpreadsheetVersion version, String start, String end) { + return new AreaReference("$A" + start + ":$" + version.getLastColumnName() + end, version); } - public static AreaReference getWholeColumn(String start, String end) { - return new AreaReference(start + "$1:" + end + "$65536"); + public static AreaReference getWholeColumn(SpreadsheetVersion version, String start, String end) { + return new AreaReference(start + "$1:" + end + "$" + version.getMaxRows(), version); } /** * Is the reference for a whole-column reference, * such as C:C or D:G ? */ - public static boolean isWholeColumnReference(CellReference topLeft, CellReference botRight) { + public static boolean isWholeColumnReference(SpreadsheetVersion version, CellReference topLeft, CellReference botRight) { + if (null == version) { + version = SpreadsheetVersion.EXCEL97; // how the code used to behave. + } + // These are represented as something like // C$1:C$65535 or D$1:F$0 // i.e. absolute from 1st row to 0th one if(topLeft.getRow() == 0 && topLeft.isRowAbsolute() && - botRight.getRow() == SpreadsheetVersion.EXCEL97.getLastRowIndex() && botRight.isRowAbsolute()) { + botRight.getRow() == version.getLastRowIndex() && botRight.isRowAbsolute()) { return true; } return false; } public boolean isWholeColumnReference() { - return isWholeColumnReference(_firstCell, _lastCell); + return isWholeColumnReference(_version, _firstCell, _lastCell); } /** diff --git a/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java b/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java index 234322671..4b5b10424 100644 --- a/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java +++ b/src/java/org/apache/poi/ss/util/CellRangeAddressBase.java @@ -24,8 +24,6 @@ import org.apache.poi.ss.SpreadsheetVersion; * See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'

    * * Common subclass of 8-bit and 16-bit versions - * - * @author Josh Micich */ public abstract class CellRangeAddressBase { diff --git a/src/java/org/apache/poi/ss/util/SheetUtil.java b/src/java/org/apache/poi/ss/util/SheetUtil.java index 6b55e223f..cc322293a 100644 --- a/src/java/org/apache/poi/ss/util/SheetUtil.java +++ b/src/java/org/apache/poi/ss/util/SheetUtil.java @@ -93,10 +93,9 @@ public class SheetUtil { * @param defaultCharWidth the width of a single character * @param formatter formatter used to prepare the text to be measured * @param useMergedCells whether to use merged cells - * @return the width in pixels + * @return the width in pixels or -1 if cell is empty */ public static double getCellWidth(Cell cell, int defaultCharWidth, DataFormatter formatter, boolean useMergedCells) { - Sheet sheet = cell.getSheet(); Workbook wb = sheet.getWorkbook(); Row row = cell.getRow(); @@ -123,9 +122,6 @@ public class SheetUtil { Font font = wb.getFontAt(style.getFontIndex()); - AttributedString str; - TextLayout layout; - double width = -1; if (cellType == Cell.CELL_TYPE_STRING) { RichTextString rt = cell.getRichStringCellValue(); @@ -133,30 +129,14 @@ public class SheetUtil { for (int i = 0; i < lines.length; i++) { String txt = lines[i] + defaultChar; - str = new AttributedString(txt); + AttributedString str = new AttributedString(txt); copyAttributes(font, str, 0, txt.length()); if (rt.numFormattingRuns() > 0) { // TODO: support rich text fragments } - layout = new TextLayout(str.getIterator(), fontRenderContext); - if(style.getRotation() != 0){ - /* - * Transform the text using a scale so that it's height is increased by a multiple of the leading, - * and then rotate the text before computing the bounds. The scale results in some whitespace around - * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but - * is added by the standard Excel autosize. - */ - AffineTransform trans = new AffineTransform(); - trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); - trans.concatenate( - AffineTransform.getScaleInstance(1, fontHeightMultiple) - ); - width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); - } else { - width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); - } + width = getCellWidth(defaultCharWidth, colspan, style, width, str); } } else { String sval = null; @@ -172,66 +152,49 @@ public class SheetUtil { } if(sval != null) { String txt = sval + defaultChar; - str = new AttributedString(txt); + AttributedString str = new AttributedString(txt); copyAttributes(font, str, 0, txt.length()); - layout = new TextLayout(str.getIterator(), fontRenderContext); - if(style.getRotation() != 0){ - /* - * Transform the text using a scale so that it's height is increased by a multiple of the leading, - * and then rotate the text before computing the bounds. The scale results in some whitespace around - * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but - * is added by the standard Excel autosize. - */ - AffineTransform trans = new AffineTransform(); - trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); - trans.concatenate( - AffineTransform.getScaleInstance(1, fontHeightMultiple) - ); - width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); - } else { - width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + cell.getCellStyle().getIndention()); - } + width = getCellWidth(defaultCharWidth, colspan, style, width, str); } } return width; } + private static double getCellWidth(int defaultCharWidth, int colspan, + CellStyle style, double width, AttributedString str) { + TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext); + if(style.getRotation() != 0){ + /* + * Transform the text using a scale so that it's height is increased by a multiple of the leading, + * and then rotate the text before computing the bounds. The scale results in some whitespace around + * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but + * is added by the standard Excel autosize. + */ + AffineTransform trans = new AffineTransform(); + trans.concatenate(AffineTransform.getRotateInstance(style.getRotation()*2.0*Math.PI/360.0)); + trans.concatenate( + AffineTransform.getScaleInstance(1, fontHeightMultiple) + ); + width = Math.max(width, ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth) + style.getIndention()); + } else { + width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth) + style.getIndention()); + } + return width; + } + /** * Compute width of a column and return the result * * @param sheet the sheet to calculate * @param column 0-based index of the column * @param useMergedCells whether to use merged cells - * @return the width in pixels + * @return the width in pixels or -1 if all cells are empty */ - public static double getColumnWidth(Sheet sheet, int column, boolean useMergedCells){ - AttributedString str; - TextLayout layout; - - Workbook wb = sheet.getWorkbook(); - DataFormatter formatter = new DataFormatter(); - Font defaultFont = wb.getFontAt((short) 0); - - str = new AttributedString(String.valueOf(defaultChar)); - copyAttributes(defaultFont, str, 0, 1); - layout = new TextLayout(str.getIterator(), fontRenderContext); - int defaultCharWidth = (int)layout.getAdvance(); - - double width = -1; - for (Row row : sheet) { - Cell cell = row.getCell(column); - - if (cell == null) { - continue; - } - - double cellWidth = getCellWidth(cell, defaultCharWidth, formatter, useMergedCells); - width = Math.max(width, cellWidth); - } - return width; + public static double getColumnWidth(Sheet sheet, int column, boolean useMergedCells) { + return getColumnWidth(sheet, column, useMergedCells, sheet.getFirstRowNum(), sheet.getLastRowNum()); } - + /** * Compute width of a column based on a subset of the rows and return the result * @@ -240,19 +203,16 @@ public class SheetUtil { * @param useMergedCells whether to use merged cells * @param firstRow 0-based index of the first row to consider (inclusive) * @param lastRow 0-based index of the last row to consider (inclusive) - * @return the width in pixels + * @return the width in pixels or -1 if cell is empty */ public static double getColumnWidth(Sheet sheet, int column, boolean useMergedCells, int firstRow, int lastRow){ - AttributedString str; - TextLayout layout; - Workbook wb = sheet.getWorkbook(); DataFormatter formatter = new DataFormatter(); Font defaultFont = wb.getFontAt((short) 0); - str = new AttributedString(String.valueOf(defaultChar)); + AttributedString str = new AttributedString(String.valueOf(defaultChar)); copyAttributes(defaultFont, str, 0, 1); - layout = new TextLayout(str.getIterator(), fontRenderContext); + TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext); int defaultCharWidth = (int)layout.getAdvance(); double width = -1; @@ -273,6 +233,30 @@ public class SheetUtil { return width; } + /** + * Check if the Fonts are installed correctly so that Java can compute the size of + * columns. + * + * If a Cell uses a Font which is not available on the operating system then Java may + * fail to return useful Font metrics and thus lead to an auto-computed size of 0. + * + * This method allows to check if computing the sizes for a given Font will succeed or not. + * + * @param font The Font that is used in the Cell + * @return true if computing the size for this Font will succeed, false otherwise + */ + public static boolean canComputeColumnWidht(Font font) { + AttributedString str = new AttributedString("1"); + copyAttributes(font, str, 0, "1".length()); + + TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext); + if(layout.getBounds().getWidth() > 0) { + return true; + } + + return false; + } + /** * Copy text attributes from the supplied Font to Java2D AttributedString */ diff --git a/src/java/org/apache/poi/util/BitFieldFactory.java b/src/java/org/apache/poi/util/BitFieldFactory.java index 4159074d7..047d5cb1d 100644 --- a/src/java/org/apache/poi/util/BitFieldFactory.java +++ b/src/java/org/apache/poi/util/BitFieldFactory.java @@ -21,11 +21,8 @@ package org.apache.poi.util; import java.util.*; /** - * Returns immutable Btfield instances. - * - * @author Jason Height (jheight at apache dot org) + * Returns immutable Bitfield instances. */ - public class BitFieldFactory { private static Map instances = new HashMap(); diff --git a/src/java/org/apache/poi/util/CloseIgnoringInputStream.java b/src/java/org/apache/poi/util/CloseIgnoringInputStream.java index f4896a831..66e42c258 100644 --- a/src/java/org/apache/poi/util/CloseIgnoringInputStream.java +++ b/src/java/org/apache/poi/util/CloseIgnoringInputStream.java @@ -20,13 +20,11 @@ package org.apache.poi.util; import java.io.FilterInputStream; import java.io.InputStream; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; - /** * A wrapper around an {@link InputStream}, which * ignores close requests made to it. * - * Useful with {@link POIFSFileSystem}, where you want + * Useful with {@link org.apache.poi.poifs.filesystem.POIFSFileSystem}, where you want * to control the close yourself. */ public class CloseIgnoringInputStream extends FilterInputStream { diff --git a/src/java/org/apache/poi/util/DrawingDump.java b/src/java/org/apache/poi/util/DrawingDump.java index 1055ab2da..4eb6a2aff 100644 --- a/src/java/org/apache/poi/util/DrawingDump.java +++ b/src/java/org/apache/poi/util/DrawingDump.java @@ -18,12 +18,12 @@ package org.apache.poi.util; +import java.io.File; +import java.io.IOException; + import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; - -import java.io.FileInputStream; -import java.io.IOException; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; /** * Dump out the aggregated escher records @@ -32,8 +32,8 @@ public class DrawingDump { public static void main( String[] args ) throws IOException { - POIFSFileSystem fs = - new POIFSFileSystem(new FileInputStream(args[0])); + NPOIFSFileSystem fs = + new NPOIFSFileSystem(new File(args[0])); HSSFWorkbook wb = new HSSFWorkbook(fs); try { System.out.println( "Drawing group:" ); diff --git a/src/java/org/apache/poi/util/HexDump.java b/src/java/org/apache/poi/util/HexDump.java index 3c086ba60..02d9b6ae3 100644 --- a/src/java/org/apache/poi/util/HexDump.java +++ b/src/java/org/apache/poi/util/HexDump.java @@ -245,12 +245,15 @@ public class HexDump { { StringBuffer retVal = new StringBuffer(); retVal.append('['); - for(int x = 0; x < value.length; x++) + if (value != null && value.length > 0) { - if (x>0) { - retVal.append(", "); + for(int x = 0; x < value.length; x++) + { + if (x>0) { + retVal.append(", "); + } + retVal.append(toHex(value[x])); } - retVal.append(toHex(value[x])); } retVal.append(']'); return retVal.toString(); diff --git a/src/java/org/apache/poi/util/IOUtils.java b/src/java/org/apache/poi/util/IOUtils.java index 4f18214c4..f1d5a2378 100644 --- a/src/java/org/apache/poi/util/IOUtils.java +++ b/src/java/org/apache/poi/util/IOUtils.java @@ -22,120 +22,149 @@ import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.PushbackInputStream; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.util.zip.CRC32; import java.util.zip.Checksum; +import org.apache.poi.EmptyFileException; + public final class IOUtils { + private static final POILogger logger = POILogFactory.getLogger( IOUtils.class ); - private static final POILogger logger = POILogFactory - .getLogger( IOUtils.class ); + private IOUtils() { + // no instances of this class + } - private IOUtils() { - // no instances of this class - } + /** + * Peeks at the first 8 bytes of the stream. Returns those bytes, but + * with the stream unaffected. Requires a stream that supports mark/reset, + * or a PushbackInputStream. If the stream has >0 but <8 bytes, + * remaining bytes will be zero. + * @throws EmptyFileException if the stream is empty + */ + public static byte[] peekFirst8Bytes(InputStream stream) throws IOException, EmptyFileException { + // We want to peek at the first 8 bytes + stream.mark(8); - /** - * Reads all the data from the input stream, and returns the bytes read. - */ - public static byte[] toByteArray(InputStream stream) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] header = new byte[8]; + int read = IOUtils.readFully(stream, header); - byte[] buffer = new byte[4096]; - int read = 0; - while (read != -1) { - read = stream.read(buffer); - if (read > 0) { - baos.write(buffer, 0, read); - } - } + if (read < 1) + throw new EmptyFileException(); - return baos.toByteArray(); - } + // Wind back those 8 bytes + if(stream instanceof PushbackInputStream) { + PushbackInputStream pin = (PushbackInputStream)stream; + pin.unread(header); + } else { + stream.reset(); + } - /** - * Returns an array (that shouldn't be written to!) of the - * ByteBuffer. Will be of the requested length, or possibly - * longer if that's easier. - */ - public static byte[] toByteArray(ByteBuffer buffer, int length) { - if(buffer.hasArray() && buffer.arrayOffset() == 0) { - // The backing array should work out fine for us - return buffer.array(); - } - - byte[] data = new byte[length]; - buffer.get(data); - return data; - } + return header; + } - /** - * Helper method, just calls readFully(in, b, 0, b.length) - */ - public static int readFully(InputStream in, byte[] b) throws IOException { - return readFully(in, b, 0, b.length); - } + /** + * Reads all the data from the input stream, and returns the bytes read. + */ + public static byte[] toByteArray(InputStream stream) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); - /** - * Same as the normal in.read(b, off, len), but tries to ensure - * that the entire len number of bytes is read. - *

    - * If the end of file is reached before any bytes are read, returns -1. If - * the end of the file is reached after some bytes are read, returns the - * number of bytes read. If the end of the file isn't reached before len - * bytes have been read, will return len bytes. - */ - public static int readFully(InputStream in, byte[] b, int off, int len) throws IOException { - int total = 0; - while (true) { - int got = in.read(b, off + total, len - total); - if (got < 0) { - return (total == 0) ? -1 : total; - } - total += got; - if (total == len) { - return total; - } - } - } - - /** - * Same as the normal channel.read(b), but tries to ensure - * that the entire len number of bytes is read. - *

    - * If the end of file is reached before any bytes are read, returns -1. If - * the end of the file is reached after some bytes are read, returns the - * number of bytes read. If the end of the file isn't reached before len - * bytes have been read, will return len bytes. - */ - public static int readFully(ReadableByteChannel channel, ByteBuffer b) throws IOException { - int total = 0; - while (true) { - int got = channel.read(b); - if (got < 0) { - return (total == 0) ? -1 : total; - } - total += got; - if (total == b.capacity() || b.position() == b.capacity()) { - return total; - } - } - } - - /** - * Copies all the data from the given InputStream to the OutputStream. It - * leaves both streams open, so you will still need to close them once done. - */ - public static void copy(InputStream inp, OutputStream out) throws IOException { - byte[] buff = new byte[4096]; - int count; - while ((count = inp.read(buff)) != -1) { - if (count > 0) { - out.write(buff, 0, count); - } - } - } + byte[] buffer = new byte[4096]; + int read = 0; + while (read != -1) { + read = stream.read(buffer); + if (read > 0) { + baos.write(buffer, 0, read); + } + } + + return baos.toByteArray(); + } + + /** + * Returns an array (that shouldn't be written to!) of the + * ByteBuffer. Will be of the requested length, or possibly + * longer if that's easier. + */ + public static byte[] toByteArray(ByteBuffer buffer, int length) { + if(buffer.hasArray() && buffer.arrayOffset() == 0) { + // The backing array should work out fine for us + return buffer.array(); + } + + byte[] data = new byte[length]; + buffer.get(data); + return data; + } + + /** + * Helper method, just calls readFully(in, b, 0, b.length) + */ + public static int readFully(InputStream in, byte[] b) throws IOException { + return readFully(in, b, 0, b.length); + } + + /** + * Same as the normal in.read(b, off, len), but tries to ensure + * that the entire len number of bytes is read. + *

    + * If the end of file is reached before any bytes are read, returns -1. If + * the end of the file is reached after some bytes are read, returns the + * number of bytes read. If the end of the file isn't reached before len + * bytes have been read, will return len bytes. + */ + public static int readFully(InputStream in, byte[] b, int off, int len) throws IOException { + int total = 0; + while (true) { + int got = in.read(b, off + total, len - total); + if (got < 0) { + return (total == 0) ? -1 : total; + } + total += got; + if (total == len) { + return total; + } + } + } + + /** + * Same as the normal channel.read(b), but tries to ensure + * that the entire len number of bytes is read. + *

    + * If the end of file is reached before any bytes are read, returns -1. If + * the end of the file is reached after some bytes are read, returns the + * number of bytes read. If the end of the file isn't reached before len + * bytes have been read, will return len bytes. + */ + public static int readFully(ReadableByteChannel channel, ByteBuffer b) throws IOException { + int total = 0; + while (true) { + int got = channel.read(b); + if (got < 0) { + return (total == 0) ? -1 : total; + } + total += got; + if (total == b.capacity() || b.position() == b.capacity()) { + return total; + } + } + } + + /** + * Copies all the data from the given InputStream to the OutputStream. It + * leaves both streams open, so you will still need to close them once done. + */ + public static void copy(InputStream inp, OutputStream out) throws IOException { + byte[] buff = new byte[4096]; + int count; + while ((count = inp.read(buff)) != -1) { + if (count > 0) { + out.write(buff, 0, count); + } + } + } public static long calculateChecksum(byte[] data) { Checksum sum = new CRC32(); @@ -150,14 +179,10 @@ public final class IOUtils { * @param closeable * resource to close */ - public static void closeQuietly( final Closeable closeable ) - { - try - { + public static void closeQuietly( final Closeable closeable ) { + try { closeable.close(); - } - catch ( Exception exc ) - { + } catch ( Exception exc ) { logger.log( POILogger.ERROR, "Unable to close resource: " + exc, exc ); } diff --git a/src/java/org/apache/poi/util/NullLogger.java b/src/java/org/apache/poi/util/NullLogger.java index 95c8c5d44..24643c8fd 100644 --- a/src/java/org/apache/poi/util/NullLogger.java +++ b/src/java/org/apache/poi/util/NullLogger.java @@ -27,12 +27,10 @@ package org.apache.poi.util; * @author Glen Stampoultzis (glens at apache.org) * @author Nicola Ken Barozzi (nicolaken at apache.org) */ -public class NullLogger extends POILogger -{ +public class NullLogger extends POILogger { @Override - public void initialize(final String cat) - { - //do nothing + public void initialize(final String cat){ + // do nothing } /** @@ -45,147 +43,7 @@ public class NullLogger extends POILogger @Override public void log(final int level, final Object obj1) { - //do nothing - } - - /** - * Check if a logger is enabled to log at the specified level - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - */ - - @Override - public boolean check(final int level) - { - return false; - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first object to place in the message - * @param obj2 second object to place in the message - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - * @param obj5 fifth Object to place in the message - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, final Object obj5) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - * @param obj5 fifth Object to place in the message - * @param obj6 sixth Object to place in the message - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, final Object obj5, - final Object obj6) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - * @param obj5 fifth Object to place in the message - * @param obj6 sixth Object to place in the message - * @param obj7 seventh Object to place in the message - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, final Object obj5, - final Object obj6, final Object obj7) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - * @param obj5 fifth Object to place in the message - * @param obj6 sixth Object to place in the message - * @param obj7 seventh Object to place in the message - * @param obj8 eighth Object to place in the message - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, final Object obj5, - final Object obj6, final Object obj7, final Object obj8) - { - //do nothing + // do nothing } /** @@ -195,289 +53,19 @@ public class NullLogger extends POILogger * @param obj1 The object to log. This is converted to a string. * @param exception An exception to be logged */ - - @Override - public void log(final int level, final Object obj1, - final Throwable exception) - { - //do nothing + public void log(int level, Object obj1, final Throwable exception) { + // do nothing } + /** - * Log a message. Lazily appends Object parameters together. + * Check if a logger is enabled to log at the specified level * * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param exception An exception to be logged */ - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Throwable exception) - { - //do nothing + public boolean check(final int level) { + return false; } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param exception An error message to be logged - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Throwable exception) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param exception An exception to be logged - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, - final Throwable exception) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param obj5 fifth object to place in the message - * @param exception An exception to be logged - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, final Object obj5, - final Throwable exception) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param obj5 fifth object to place in the message - * @param obj6 sixth object to place in the message - * @param exception An exception to be logged - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, final Object obj5, - final Object obj6, final Throwable exception) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param obj5 fifth object to place in the message - * @param obj6 sixth object to place in the message - * @param obj7 seventh object to place in the message - * @param exception An exception to be logged - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, final Object obj5, - final Object obj6, final Object obj7, - final Throwable exception) - { - //do nothing - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param obj5 fifth object to place in the message - * @param obj6 sixth object to place in the message - * @param obj7 seventh object to place in the message - * @param obj8 eighth object to place in the message - * @param exception An exception to be logged - */ - - @Override - public void log(final int level, final Object obj1, final Object obj2, - final Object obj3, final Object obj4, final Object obj5, - final Object obj6, final Object obj7, final Object obj8, - final Throwable exception) - { - //do nothing - } - - /** - * Logs a formated message. The message itself may contain % - * characters as place holders. This routine will attempt to match - * the placeholder by looking at the type of parameter passed to - * obj1.

    - * - * If the parameter is an array, it traverses the array first and - * matches parameters sequentially against the array items. - * Otherwise the parameters after message are matched - * in order.

    - * - * If the place holder matches against a number it is printed as a - * whole number. This can be overridden by specifying a precision - * in the form %n.m where n is the padding for the whole part and - * m is the number of decimal places to display. n can be excluded - * if desired. n and m may not be more than 9.

    - * - * If the last parameter (after flattening) is a Throwable it is - * logged specially. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param message The message to log. - * @param obj1 The first object to match against. - */ - - @Override - public void logFormatted(final int level, final String message, - final Object obj1) - { - //do nothing - } - - /** - * Logs a formated message. The message itself may contain % - * characters as place holders. This routine will attempt to match - * the placeholder by looking at the type of parameter passed to - * obj1.

    - * - * If the parameter is an array, it traverses the array first and - * matches parameters sequentially against the array items. - * Otherwise the parameters after message are matched - * in order.

    - * - * If the place holder matches against a number it is printed as a - * whole number. This can be overridden by specifying a precision - * in the form %n.m where n is the padding for the whole part and - * m is the number of decimal places to display. n can be excluded - * if desired. n and m may not be more than 9.

    - * - * If the last parameter (after flattening) is a Throwable it is - * logged specially. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param message The message to log. - * @param obj1 The first object to match against. - * @param obj2 The second object to match against. - */ - - @Override - public void logFormatted(final int level, final String message, - final Object obj1, final Object obj2) - { - //do nothing - } - - /** - * Logs a formated message. The message itself may contain % - * characters as place holders. This routine will attempt to match - * the placeholder by looking at the type of parameter passed to - * obj1.

    - * - * If the parameter is an array, it traverses the array first and - * matches parameters sequentially against the array items. - * Otherwise the parameters after message are matched - * in order.

    - * - * If the place holder matches against a number it is printed as a - * whole number. This can be overridden by specifying a precision - * in the form %n.m where n is the padding for the whole part and - * m is the number of decimal places to display. n can be excluded - * if desired. n and m may not be more than 9.

    - * - * If the last parameter (after flattening) is a Throwable it is - * logged specially. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param message The message to log. - * @param obj1 The first object to match against. - * @param obj2 The second object to match against. - * @param obj3 The third object to match against. - */ - - @Override - public void logFormatted(final int level, final String message, - final Object obj1, final Object obj2, - final Object obj3) - { - //do nothing - } - - /** - * Logs a formated message. The message itself may contain % - * characters as place holders. This routine will attempt to match - * the placeholder by looking at the type of parameter passed to - * obj1.

    - * - * If the parameter is an array, it traverses the array first and - * matches parameters sequentially against the array items. - * Otherwise the parameters after message are matched - * in order.

    - * - * If the place holder matches against a number it is printed as a - * whole number. This can be overridden by specifying a precision - * in the form %n.m where n is the padding for the whole part and - * m is the number of decimal places to display. n can be excluded - * if desired. n and m may not be more than 9.

    - * - * If the last parameter (after flattening) is a Throwable it is - * logged specially. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param message The message to log. - * @param obj1 The first object to match against. - * @param obj2 The second object to match against. - * @param obj3 The third object to match against. - * @param obj4 The forth object to match against. - */ - - @Override - public void logFormatted(final int level, final String message, - final Object obj1, final Object obj2, - final Object obj3, final Object obj4) - { - //do nothing - } - } diff --git a/src/java/org/apache/poi/util/POILogFactory.java b/src/java/org/apache/poi/util/POILogFactory.java index 641949c39..7af73e3a8 100644 --- a/src/java/org/apache/poi/util/POILogFactory.java +++ b/src/java/org/apache/poi/util/POILogFactory.java @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.util; @@ -30,20 +30,18 @@ import java.util.Map; * @author Marc Johnson (mjohnson at apache dot org) * @author Nicola Ken Barozzi (nicolaken at apache.org) */ - -public class POILogFactory -{ - +@Internal +public final class POILogFactory { /** * Map of POILogger instances, with classes as keys */ - private static Map _loggers = new HashMap();; + private static Map _loggers = new HashMap(); /** * A common instance of NullLogger, as it does nothing * we only need the one */ - private static POILogger _nullLogger = new NullLogger(); + private static final POILogger _nullLogger = new NullLogger(); /** * The name of the class to use. Initialised the * first time we need it @@ -53,9 +51,7 @@ public class POILogFactory /** * Construct a POILogFactory. */ - private POILogFactory() - { - } + private POILogFactory() {} /** * Get a logger, based on a class name @@ -64,12 +60,10 @@ public class POILogFactory * * @return a POILogger for the specified class */ - - public static POILogger getLogger(final Class theclass) - { + public static POILogger getLogger(final Class theclass) { return getLogger(theclass.getName()); } - + /** * Get a logger, based on a String * @@ -77,11 +71,9 @@ public class POILogFactory * * @return a POILogger for the specified class */ - - public static POILogger getLogger(final String cat) - { + public static POILogger getLogger(final String cat) { POILogger logger = null; - + // If we haven't found out what logger to use yet, // then do so now // Don't look it up until we're first asked, so @@ -91,40 +83,40 @@ public class POILogFactory try { _loggerClassName = System.getProperty("org.apache.poi.util.POILogger"); } catch(Exception e) {} - + // Use the default logger if none specified, // or none could be fetched if(_loggerClassName == null) { - _loggerClassName = _nullLogger.getClass().getName(); + _loggerClassName = _nullLogger.getClass().getName(); } } - + // Short circuit for the null logger, which // ignores all categories if(_loggerClassName.equals(_nullLogger.getClass().getName())) { return _nullLogger; } - + // Fetch the right logger for them, creating - // it if that's required - if (_loggers.containsKey(cat)) { - logger = _loggers.get(cat); - } else { + // it if that's required + logger = _loggers.get(cat); + if (logger == null) { try { - @SuppressWarnings("unchecked") - Class loggerClass = - (Class)Class.forName(_loggerClassName); - logger = loggerClass.newInstance(); - logger.initialize(cat); + @SuppressWarnings("unchecked") + Class loggerClass = + (Class) Class.forName(_loggerClassName); + logger = loggerClass.newInstance(); + logger.initialize(cat); } catch(Exception e) { - // Give up and use the null logger - logger = _nullLogger; + // Give up and use the null logger + logger = _nullLogger; + _loggerClassName = _nullLogger.getClass().getName(); } - + // Save for next time _loggers.put(cat, logger); } return logger; } -} // end public class POILogFactory \ No newline at end of file +} \ No newline at end of file diff --git a/src/java/org/apache/poi/util/POILogger.java b/src/java/org/apache/poi/util/POILogger.java index 4088ec290..d892366e7 100644 --- a/src/java/org/apache/poi/util/POILogger.java +++ b/src/java/org/apache/poi/util/POILogger.java @@ -30,6 +30,7 @@ import java.util.List; * @author Glen Stampoultzis (glens at apache.org) * @author Nicola Ken Barozzi (nicolaken at apache.org) */ +@Internal public abstract class POILogger { public static final int DEBUG = 1; @@ -49,7 +50,7 @@ public abstract class POILogger { * package. You need a POILogger? Go to the POILogFactory for one */ POILogger() { - // no fields to initialise + // no fields to initialize } abstract public void initialize(String cat); @@ -60,7 +61,7 @@ public abstract class POILogger { * @param level One of DEBUG, INFO, WARN, ERROR, FATAL * @param obj1 The object to log. This is converted to a string. */ - abstract public void log(int level, Object obj1); + abstract protected void log(int level, Object obj1); /** * Log a message @@ -69,8 +70,7 @@ public abstract class POILogger { * @param obj1 The object to log. This is converted to a string. * @param exception An exception to be logged */ - abstract public void log(int level, Object obj1, - final Throwable exception); + abstract protected void log(int level, Object obj1, final Throwable exception); /** @@ -82,602 +82,118 @@ public abstract class POILogger { /** * Log a message. Lazily appends Object parameters together. + * If the last parameter is a {@link Throwable} it is logged specially. * * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first object to place in the message - * @param obj2 second object to place in the message + * @param objs the objects to place in the message */ - public void log(int level, Object obj1, Object obj2) - { - if (check(level)) - { - log(level, new StringBuffer(32).append(obj1).append(obj2)); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - */ - public void log(int level, Object obj1, Object obj2, - Object obj3) - { - - - if (check(level)) - { - log(level, - new StringBuffer(48).append(obj1).append(obj2) - .append(obj3)); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4) - { - - - if (check(level)) - { - log(level, - new StringBuffer(64).append(obj1).append(obj2) - .append(obj3).append(obj4)); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - * @param obj5 fifth Object to place in the message - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, Object obj5) - { - - - if (check(level)) - { - log(level, - new StringBuffer(80).append(obj1).append(obj2) - .append(obj3).append(obj4).append(obj5)); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - * @param obj5 fifth Object to place in the message - * @param obj6 sixth Object to place in the message - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, Object obj5, - Object obj6) - { - - - if (check(level)) - { - log(level , - new StringBuffer(96).append(obj1).append(obj2) - .append(obj3).append(obj4).append(obj5).append(obj6)); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - * @param obj5 fifth Object to place in the message - * @param obj6 sixth Object to place in the message - * @param obj7 seventh Object to place in the message - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, Object obj5, - Object obj6, Object obj7) - { - - - if (check(level)) - { - log(level, - new StringBuffer(112).append(obj1).append(obj2) - .append(obj3).append(obj4).append(obj5).append(obj6) - .append(obj7)); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third Object to place in the message - * @param obj4 fourth Object to place in the message - * @param obj5 fifth Object to place in the message - * @param obj6 sixth Object to place in the message - * @param obj7 seventh Object to place in the message - * @param obj8 eighth Object to place in the message - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, Object obj5, - Object obj6, Object obj7, Object obj8) - { - - - if (check(level)) - { - log(level, - new StringBuffer(128).append(obj1).append(obj2) - .append(obj3).append(obj4).append(obj5).append(obj6) - .append(obj7).append(obj8)); - } - } - - /** - * Log an exception, without a message - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param exception An exception to be logged - */ - public void log(int level, final Throwable exception) - { - log(level, null, exception); - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param exception An exception to be logged - */ - public void log(int level, Object obj1, Object obj2, - final Throwable exception) - { - - - if (check(level)) - { - log(level, new StringBuffer(32).append(obj1).append(obj2), - exception); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param exception An error message to be logged - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, final Throwable exception) - { - - - if (check(level)) - { - log(level, new StringBuffer(48).append(obj1).append(obj2) - .append(obj3), exception); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param exception An exception to be logged - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, - final Throwable exception) - { - - - if (check(level)) - { - log(level, new StringBuffer(64).append(obj1).append(obj2) - .append(obj3).append(obj4), exception); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param obj5 fifth object to place in the message - * @param exception An exception to be logged - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, Object obj5, - final Throwable exception) - { - - - if (check(level)) - { - log(level, new StringBuffer(80).append(obj1).append(obj2) - .append(obj3).append(obj4).append(obj5), exception); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param obj5 fifth object to place in the message - * @param obj6 sixth object to place in the message - * @param exception An exception to be logged - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, Object obj5, - Object obj6, final Throwable exception) - { - - - if (check(level)) - { - log(level , new StringBuffer(96).append(obj1) - .append(obj2).append(obj3).append(obj4).append(obj5) - .append(obj6), exception); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param obj5 fifth object to place in the message - * @param obj6 sixth object to place in the message - * @param obj7 seventh object to place in the message - * @param exception An exception to be logged - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, Object obj5, - Object obj6, Object obj7, - final Throwable exception) - { - - - if (check(level)) - { - log(level, new StringBuffer(112).append(obj1).append(obj2) - .append(obj3).append(obj4).append(obj5).append(obj6) - .append(obj7), exception); - } - } - - /** - * Log a message. Lazily appends Object parameters together. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param obj1 first Object to place in the message - * @param obj2 second Object to place in the message - * @param obj3 third object to place in the message - * @param obj4 fourth object to place in the message - * @param obj5 fifth object to place in the message - * @param obj6 sixth object to place in the message - * @param obj7 seventh object to place in the message - * @param obj8 eighth object to place in the message - * @param exception An exception to be logged - */ - public void log(int level, Object obj1, Object obj2, - Object obj3, Object obj4, Object obj5, - Object obj6, Object obj7, Object obj8, - final Throwable exception) - { - - - if (check(level)) - { - log(level, new StringBuffer(128).append(obj1).append(obj2) - .append(obj3).append(obj4).append(obj5).append(obj6) - .append(obj7).append(obj8), exception); - } - } - - /** - * Logs a formated message. The message itself may contain % - * characters as place holders. This routine will attempt to match - * the placeholder by looking at the type of parameter passed to - * obj1.

    - * - * If the parameter is an array, it traverses the array first and - * matches parameters sequentially against the array items. - * Otherwise the parameters after message are matched - * in order.

    - * - * If the place holder matches against a number it is printed as a - * whole number. This can be overridden by specifying a precision - * in the form %n.m where n is the padding for the whole part and - * m is the number of decimal places to display. n can be excluded - * if desired. n and m may not be more than 9.

    - * - * If the last parameter (after flattening) is a Throwable it is - * logged specially. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param message The message to log. - * @param obj1 The first object to match against. - */ - public void logFormatted(int level, String message, - Object obj1) - { - commonLogFormatted(level, message, new Object[] - { - obj1 - }); - } - - /** - * Logs a formated message. The message itself may contain % - * characters as place holders. This routine will attempt to match - * the placeholder by looking at the type of parameter passed to - * obj1.

    - * - * If the parameter is an array, it traverses the array first and - * matches parameters sequentially against the array items. - * Otherwise the parameters after message are matched - * in order.

    - * - * If the place holder matches against a number it is printed as a - * whole number. This can be overridden by specifying a precision - * in the form %n.m where n is the padding for the whole part and - * m is the number of decimal places to display. n can be excluded - * if desired. n and m may not be more than 9.

    - * - * If the last parameter (after flattening) is a Throwable it is - * logged specially. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param message The message to log. - * @param obj1 The first object to match against. - * @param obj2 The second object to match against. - */ - public void logFormatted(int level, String message, - Object obj1, Object obj2) - { - commonLogFormatted(level, message, new Object[] - { - obj1, obj2 - }); - } - - /** - * Logs a formated message. The message itself may contain % - * characters as place holders. This routine will attempt to match - * the placeholder by looking at the type of parameter passed to - * obj1.

    - * - * If the parameter is an array, it traverses the array first and - * matches parameters sequentially against the array items. - * Otherwise the parameters after message are matched - * in order.

    - * - * If the place holder matches against a number it is printed as a - * whole number. This can be overridden by specifying a precision - * in the form %n.m where n is the padding for the whole part and - * m is the number of decimal places to display. n can be excluded - * if desired. n and m may not be more than 9.

    - * - * If the last parameter (after flattening) is a Throwable it is - * logged specially. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param message The message to log. - * @param obj1 The first object to match against. - * @param obj2 The second object to match against. - * @param obj3 The third object to match against. - */ - public void logFormatted(int level, String message, - Object obj1, Object obj2, - Object obj3) - { - commonLogFormatted(level, message, new Object[] - { - obj1, obj2, obj3 - }); - } - - /** - * Logs a formated message. The message itself may contain % - * characters as place holders. This routine will attempt to match - * the placeholder by looking at the type of parameter passed to - * obj1.

    - * - * If the parameter is an array, it traverses the array first and - * matches parameters sequentially against the array items. - * Otherwise the parameters after message are matched - * in order.

    - * - * If the place holder matches against a number it is printed as a - * whole number. This can be overridden by specifying a precision - * in the form %n.m where n is the padding for the whole part and - * m is the number of decimal places to display. n can be excluded - * if desired. n and m may not be more than 9.

    - * - * If the last parameter (after flattening) is a Throwable it is - * logged specially. - * - * @param level One of DEBUG, INFO, WARN, ERROR, FATAL - * @param message The message to log. - * @param obj1 The first object to match against. - * @param obj2 The second object to match against. - * @param obj3 The third object to match against. - * @param obj4 The forth object to match against. - */ - public void logFormatted(int level, String message, - Object obj1, Object obj2, - Object obj3, Object obj4) - { - commonLogFormatted(level, message, new Object[] - { - obj1, obj2, obj3, obj4 - }); - } - - private void commonLogFormatted(int level, String message, - Object [] unflatParams) - { - - - if (check(level)) - { - Object[] params = flattenArrays(unflatParams); - - if (params[ params.length - 1 ] instanceof Throwable) - { - log(level, StringUtil.format(message, params), - ( Throwable ) params[ params.length - 1 ]); - } - else - { - log(level, StringUtil.format(message, params)); + public void log(int level, Object... objs) { + if (!check(level)) return; + StringBuilder sb = new StringBuilder(32); + Throwable lastEx = null; + for (int i=0; i + * + * If the parameter is an array, it traverses the array first and + * matches parameters sequentially against the array items. + * Otherwise the parameters after message are matched + * in order.

    + * + * If the place holder matches against a number it is printed as a + * whole number. This can be overridden by specifying a precision + * in the form %n.m where n is the padding for the whole part and + * m is the number of decimal places to display. n can be excluded + * if desired. n and m may not be more than 9.

    + * + * If the last parameter (after flattening) is a Throwable it is + * logged specially. + * + * @param level One of DEBUG, INFO, WARN, ERROR, FATAL + * @param message The message to log. + * @param unflatParams The objects to match against. */ - private Object [] flattenArrays(Object [] objects) - { + public void logFormatted(int level, String message, Object... unflatParams) { + if (!check(level)) return; + Object[] params = flattenArrays(unflatParams); + String msg = StringUtil.format(message, params); + msg = msg.replaceAll("[\r\n]+", " "); // log forging escape + + if (params.length > 0 && params[params.length-1] instanceof Throwable) { + log(level, msg, (Throwable)params[params.length-1]); + } else { + log(level, msg); + } + } + + /** + * Flattens any contained objects. Only traverses one level deep. + */ + private Object[] flattenArrays(Object... unflatParams) { List results = new ArrayList(); - - for (int i = 0; i < objects.length; i++) - { - results.addAll(objectToObjectArray(objects[ i ])); + for (Object obj : unflatParams) { + flattenObject(results, obj); } - return results.toArray(new Object[ results.size() ]); + return results.toArray(new Object[results.size()]); } - private List objectToObjectArray(Object object) - { - List results = new ArrayList(); - - if (object instanceof byte []) - { - byte[] array = ( byte [] ) object; - - for (int j = 0; j < array.length; j++) - { - results.add(Byte.valueOf(array[ j ])); + private void flattenObject(List results, Object object) { + if (object instanceof byte[]) { + for (byte b : (byte[])object) { + results.add(Byte.valueOf(b)); } - } - if (object instanceof char []) - { - char[] array = ( char [] ) object; - - for (int j = 0; j < array.length; j++) - { - results.add(Character.valueOf(array[ j ])); + } else if (object instanceof char[]) { + for (char c : (char[])object) { + results.add(Character.valueOf(c)); } - } - else if (object instanceof short []) - { - short[] array = ( short [] ) object; - - for (int j = 0; j < array.length; j++) - { - results.add(Short.valueOf(array[ j ])); + } else if (object instanceof short[]) { + for (short s : (short[])object) { + results.add(Short.valueOf(s)); } - } - else if (object instanceof int []) - { - int[] array = ( int [] ) object; - - for (int j = 0; j < array.length; j++) - { - results.add(Integer.valueOf(array[ j ])); + } else if (object instanceof int[]) { + for (int i : (int[])object) { + results.add(Integer.valueOf(i)); } - } - else if (object instanceof long []) - { - long[] array = ( long [] ) object; - - for (int j = 0; j < array.length; j++) - { - results.add(Long.valueOf(array[ j ])); + } else if (object instanceof long[]) { + for (long l : (long[])object) { + results.add(Long.valueOf(l)); } - } - else if (object instanceof float []) - { - float[] array = ( float [] ) object; - - for (int j = 0; j < array.length; j++) - { - results.add(new Float(array[ j ])); + } else if (object instanceof float[]) { + for (float f : (float[])object) { + results.add(Float.valueOf(f)); } - } - else if (object instanceof double []) - { - double[] array = ( double [] ) object; - - for (int j = 0; j < array.length; j++) - { - results.add(new Double(array[ j ])); + } else if (object instanceof double[]) { + for (double d : (double[])object) { + results.add(Double.valueOf(d)); } - } - else if (object instanceof Object []) - { - Object[] array = ( Object [] ) object; - - for (int j = 0; j < array.length; j++) - { - results.add(array[ j ]); + } else if (object instanceof Object[]) { + for (Object o : (Object[])object) { + results.add(o); } - } - else - { + } else { results.add(object); } - return results; } } diff --git a/src/java/org/apache/poi/util/StringUtil.java b/src/java/org/apache/poi/util/StringUtil.java index 99880f500..bd417961e 100644 --- a/src/java/org/apache/poi/util/StringUtil.java +++ b/src/java/org/apache/poi/util/StringUtil.java @@ -22,6 +22,7 @@ import java.text.FieldPosition; import java.text.NumberFormat; import java.util.HashMap; import java.util.Iterator; +import java.util.Locale; import java.util.Map; import org.apache.poi.hssf.record.RecordInputStream; @@ -310,7 +311,7 @@ public class StringUtil { Number number, String formatting, StringBuffer outputTo) { - NumberFormat numberFormat = NumberFormat.getInstance(); + NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); if ((0 < formatting.length()) && Character.isDigit(formatting.charAt(0))) { numberFormat.setMinimumIntegerDigits( diff --git a/src/scratchpad/src/org/apache/poi/wp/usermodel/CharacterRun.java b/src/java/org/apache/poi/wp/usermodel/CharacterRun.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/wp/usermodel/CharacterRun.java rename to src/java/org/apache/poi/wp/usermodel/CharacterRun.java diff --git a/src/scratchpad/src/org/apache/poi/wp/usermodel/Paragraph.java b/src/java/org/apache/poi/wp/usermodel/Paragraph.java similarity index 100% rename from src/scratchpad/src/org/apache/poi/wp/usermodel/Paragraph.java rename to src/java/org/apache/poi/wp/usermodel/Paragraph.java diff --git a/src/ooxml/java/org/apache/poi/POIXMLDocument.java b/src/ooxml/java/org/apache/poi/POIXMLDocument.java index bf241f897..0e18ee112 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLDocument.java +++ b/src/ooxml/java/org/apache/poi/POIXMLDocument.java @@ -16,6 +16,7 @@ ==================================================================== */ package org.apache.poi; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -37,7 +38,7 @@ import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.util.IOUtils; import org.apache.xmlbeans.impl.common.SystemCache; -public abstract class POIXMLDocument extends POIXMLDocumentPart{ +public abstract class POIXMLDocument extends POIXMLDocumentPart implements Closeable { public static final String DOCUMENT_CREATOR = "Apache POI"; // OLE embeddings relation name @@ -171,7 +172,7 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{ * Closes the underlying {@link OPCPackage} from which this * document was read, if there is one */ - protected void close() throws IOException { + public void close() throws IOException { if (pkg != null) { if (pkg.getPackageAccess() == PackageAccess.READ) { pkg.revert(); diff --git a/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java b/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java index 24b4af238..f051eb32a 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java +++ b/src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java @@ -94,6 +94,15 @@ public class POIXMLDocumentPart { */ public POIXMLDocumentPart(OPCPackage pkg) { PackageRelationship coreRel = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT).getRelationship(0); + if (coreRel == null) { + coreRel = pkg.getRelationshipsByType(PackageRelationshipTypes.STRICT_CORE_DOCUMENT).getRelationship(0); + if (coreRel != null) { + throw new POIXMLException("Strict OOXML isn't currently supported, please see bug #57699"); + } + } + if (coreRel == null) { + throw new POIXMLException("OOXML file structure broken/invalid - no core document found!"); + } this.packagePart = pkg.getPart(coreRel); this.packageRel = coreRel; @@ -349,11 +358,27 @@ public class POIXMLDocumentPart { * @param descriptor the part descriptor * @param factory the factory that will create an instance of the requested relation * @return the created child POIXMLDocumentPart + * @throws PartAlreadyExistsException + * If rule M1.12 is not verified : Packages shall not contain + * equivalent part names and package implementers shall neither + * create nor recognize packages with equivalent part names. */ public final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory){ return createRelationship(descriptor, factory, -1, false); } + /** + * Create a new child POIXMLDocumentPart + * + * @param descriptor the part descriptor + * @param factory the factory that will create an instance of the requested relation + * @param idx part number + * @return the created child POIXMLDocumentPart + * @throws PartAlreadyExistsException + * If rule M1.12 is not verified : Packages shall not contain + * equivalent part names and package implementers shall neither + * create nor recognize packages with equivalent part names. + */ public final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx){ return createRelationship(descriptor, factory, idx, false); } @@ -366,6 +391,10 @@ public class POIXMLDocumentPart { * @param idx part number * @param noRelation if true, then no relationship is added. * @return the created child POIXMLDocumentPart + * @throws PartAlreadyExistsException + * If rule M1.12 is not verified : Packages shall not contain + * equivalent part names and package implementers shall neither + * create nor recognize packages with equivalent part names. */ protected final POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, POIXMLFactory factory, int idx, boolean noRelation){ try { diff --git a/src/ooxml/java/org/apache/poi/POIXMLPropertiesTextExtractor.java b/src/ooxml/java/org/apache/poi/POIXMLPropertiesTextExtractor.java index ce576439f..8a35a34e4 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLPropertiesTextExtractor.java +++ b/src/ooxml/java/org/apache/poi/POIXMLPropertiesTextExtractor.java @@ -67,9 +67,14 @@ public class POIXMLPropertiesTextExtractor extends POIXMLTextExtractor { * Returns the core document properties, eg author */ public String getCorePropertiesText() { + POIXMLDocument document = getDocument(); + if(document == null) { // event based extractor does not have a document + return ""; + } + StringBuffer text = new StringBuffer(); - PackagePropertiesPart props = - getDocument().getProperties().getCoreProperties().getUnderlyingProperties(); + PackagePropertiesPart props = + document.getProperties().getCoreProperties().getUnderlyingProperties(); appendIfPresent(text, "Category", props.getCategoryProperty().getValue()); appendIfPresent(text, "Category", props.getCategoryProperty().getValue()); @@ -99,9 +104,14 @@ public class POIXMLPropertiesTextExtractor extends POIXMLTextExtractor { * application */ public String getExtendedPropertiesText() { + POIXMLDocument document = getDocument(); + if(document == null) { // event based extractor does not have a document + return ""; + } + StringBuffer text = new StringBuffer(); org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties - props = getDocument().getProperties().getExtendedProperties().getUnderlyingProperties(); + props = document.getProperties().getExtendedProperties().getUnderlyingProperties(); appendIfPresent(text, "Application", props.getApplication()); appendIfPresent(text, "AppVersion", props.getAppVersion()); @@ -127,9 +137,14 @@ public class POIXMLPropertiesTextExtractor extends POIXMLTextExtractor { */ @SuppressWarnings("deprecation") public String getCustomPropertiesText() { + POIXMLDocument document = getDocument(); + if(document == null) { // event based extractor does not have a document + return ""; + } + StringBuilder text = new StringBuilder(); org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties - props = getDocument().getProperties().getCustomProperties().getUnderlyingProperties(); + props = document.getProperties().getCustomProperties().getUnderlyingProperties(); for(CTProperty property : props.getPropertyArray()) { String val = "(not implemented!)"; diff --git a/src/ooxml/java/org/apache/poi/POIXMLTextExtractor.java b/src/ooxml/java/org/apache/poi/POIXMLTextExtractor.java index 3a600f48a..705bf42a6 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLTextExtractor.java +++ b/src/ooxml/java/org/apache/poi/POIXMLTextExtractor.java @@ -32,8 +32,6 @@ public abstract class POIXMLTextExtractor extends POITextExtractor { * Creates a new text extractor for the given document */ public POIXMLTextExtractor(POIXMLDocument document) { - super((POIDocument)null); - _document = document; } diff --git a/src/ooxml/java/org/apache/poi/dev/OOXMLPrettyPrint.java b/src/ooxml/java/org/apache/poi/dev/OOXMLPrettyPrint.java index aab811287..a05af6b4d 100644 --- a/src/ooxml/java/org/apache/poi/dev/OOXMLPrettyPrint.java +++ b/src/ooxml/java/org/apache/poi/dev/OOXMLPrettyPrint.java @@ -18,7 +18,6 @@ package org.apache.poi.dev; import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -40,9 +39,10 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.apache.poi.openxml4j.opc.internal.ZipHelper; +import org.apache.poi.util.IOUtils; import org.w3c.dom.Document; import org.xml.sax.InputSource; -import org.xml.sax.SAXException; /** * Reads a zipped OOXML file and produces a copy with the included @@ -80,11 +80,10 @@ public class OOXMLPrettyPrint { } private static void handleFile(File file, File outFile) throws ZipException, - IOException, FileNotFoundException, SAXException, - TransformerException, ParserConfigurationException { + IOException, TransformerException, ParserConfigurationException { System.out.println("Reading zip-file " + file + " and writing pretty-printed XML to " + outFile); - ZipFile zipFile = new ZipFile(file); + ZipFile zipFile = ZipHelper.openZipFile(file); try { ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFile))); try { @@ -99,15 +98,24 @@ public class OOXMLPrettyPrint { } } - private void handle(ZipFile file, ZipOutputStream out) throws SAXException, IOException, TransformerException { + private void handle(ZipFile file, ZipOutputStream out) throws IOException, TransformerException { Enumeration entries = file.entries(); while(entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); - out.putNextEntry(new ZipEntry(entry.getName())); + String name = entry.getName(); + out.putNextEntry(new ZipEntry(name)); try { - Document document = documentBuilder.parse(new InputSource(file.getInputStream(entry))); - pretty(document, out, 2); + if(name.endsWith(".xml") || name.endsWith(".rels")) { + Document document = documentBuilder.parse(new InputSource(file.getInputStream(entry))); + document.setXmlStandalone(true); + pretty(document, out, 2); + } else { + System.out.println("Not pretty-printing non-XML file " + name); + IOUtils.copy(file.getInputStream(entry), out); + } + } catch (Exception e) { + throw new IOException("While handling entry " + name, e); } finally { out.closeEntry(); } diff --git a/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java b/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java index 65d1e3d69..2ef23d2da 100644 --- a/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java +++ b/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java @@ -18,7 +18,6 @@ package org.apache.poi.extractor; import java.io.ByteArrayInputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -47,10 +46,16 @@ import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; +import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.Entry; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.NotOLE2FileException; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OfficeXmlFileException; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.xslf.XSLFSlideShow; import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor; import org.apache.poi.xslf.usermodel.XSLFRelation; import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor; @@ -65,8 +70,9 @@ import org.apache.xmlbeans.XmlException; * document, and returns it. */ public class ExtractorFactory { - public static final String CORE_DOCUMENT_REL = - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; + public static final String CORE_DOCUMENT_REL = PackageRelationshipTypes.CORE_DOCUMENT; + protected static final String VISIO_DOCUMENT_REL = PackageRelationshipTypes.VISIO_CORE_DOCUMENT; + protected static final String STRICT_DOCUMENT_REL = PackageRelationshipTypes.STRICT_CORE_DOCUMENT; /** Should this thread prefer event based over usermodel based extractors? */ @@ -125,16 +131,14 @@ public class ExtractorFactory { public static POITextExtractor createExtractor(File f) throws IOException, InvalidFormatException, OpenXML4JException, XmlException { InputStream inp = null; try { - inp = new PushbackInputStream( - new FileInputStream(f), 8); - - if(POIFSFileSystem.hasPOIFSHeader(inp)) { - return createExtractor(new POIFSFileSystem(inp)); - } - if(POIXMLDocument.hasOOXMLHeader(inp)) { + try { + NPOIFSFileSystem fs = new NPOIFSFileSystem(f); + return createExtractor(fs); + } catch (OfficeXmlFileException e) { return createExtractor(OPCPackage.open(f.toString(), PackageAccess.READ)); + } catch (NotOLE2FileException ne) { + throw new IllegalArgumentException("Your File was neither an OLE2 file, nor an OOXML file"); } - throw new IllegalArgumentException("Your File was neither an OLE2 file, nor an OOXML file"); } finally { if(inp != null) inp.close(); } @@ -147,8 +151,8 @@ public class ExtractorFactory { inp = new PushbackInputStream(inp, 8); } - if(POIFSFileSystem.hasPOIFSHeader(inp)) { - return createExtractor(new POIFSFileSystem(inp)); + if(NPOIFSFileSystem.hasPOIFSHeader(inp)) { + return createExtractor(new NPOIFSFileSystem(inp)); } if(POIXMLDocument.hasOOXMLHeader(inp)) { return createExtractor(OPCPackage.open(inp)); @@ -157,12 +161,30 @@ public class ExtractorFactory { } public static POIXMLTextExtractor createExtractor(OPCPackage pkg) throws IOException, OpenXML4JException, XmlException { + // Check for the normal Office core document PackageRelationshipCollection core = pkg.getRelationshipsByType(CORE_DOCUMENT_REL); - if(core.size() != 1) { - throw new IllegalArgumentException("Invalid OOXML Package received - expected 1 core document, found " + core.size()); + + // If nothing was found, try some of the other OOXML-based core types + if (core.size() == 0) { + // Could it be an OOXML-Strict one? + core = pkg.getRelationshipsByType(STRICT_DOCUMENT_REL); + } + if (core.size() == 0) { + // Could it be a visio one? + PackageRelationshipCollection visio = + pkg.getRelationshipsByType(VISIO_DOCUMENT_REL); + if (visio.size() == 1) { + throw new IllegalArgumentException("Text extraction not supported for Visio OOXML files"); + } + } + + // Should just be a single core document, complain if not + if (core.size() != 1) { + throw new IllegalArgumentException("Invalid OOXML Package received - expected 1 core document, found " + core.size()); } + // Grab the core document part, and try to identify from that PackagePart corePart = pkg.getPart(core.getRelationship(0)); // Is it XSSF? @@ -190,6 +212,14 @@ public class ExtractorFactory { } } + // special handling for SlideShow-Theme-files, + if(XSLFRelation.THEME_MANAGER.getContentType().equals(corePart.getContentType())) { + return new XSLFPowerPointExtractor(new XSLFSlideShow(pkg)); + } + + // ensure that we close the package again if there is an error opening it, however + // we need to revert the package to not re-write the file via close(), which is very likely not wanted for a TextExtractor! + pkg.revert(); throw new IllegalArgumentException("No supported documents found in the OOXML package (found "+corePart.getContentType()+")"); } @@ -197,23 +227,23 @@ public class ExtractorFactory { // Only ever an OLE2 one from the root of the FS return (POIOLE2TextExtractor)createExtractor(fs.getRoot()); } - - /** - * @deprecated Use {@link #createExtractor(DirectoryNode)} instead - */ - @Deprecated - public static POITextExtractor createExtractor(DirectoryNode poifsDir, POIFSFileSystem fs) - throws IOException, InvalidFormatException, OpenXML4JException, XmlException - { - return createExtractor(poifsDir); - } + public static POIOLE2TextExtractor createExtractor(NPOIFSFileSystem fs) throws IOException, InvalidFormatException, OpenXML4JException, XmlException { + // Only ever an OLE2 one from the root of the FS + return (POIOLE2TextExtractor)createExtractor(fs.getRoot()); + } + public static POIOLE2TextExtractor createExtractor(OPOIFSFileSystem fs) throws IOException, InvalidFormatException, OpenXML4JException, XmlException { + // Only ever an OLE2 one from the root of the FS + return (POIOLE2TextExtractor)createExtractor(fs.getRoot()); + } public static POITextExtractor createExtractor(DirectoryNode poifsDir) throws IOException, InvalidFormatException, OpenXML4JException, XmlException { // Look for certain entries in the stream, to figure it // out from - if (poifsDir.hasEntry("Workbook")) { + if (poifsDir.hasEntry("Workbook") || + // some XLS files have different entry-names + poifsDir.hasEntry("WORKBOOK") || poifsDir.hasEntry("BOOK")) { if (getPreferEventExtractor()) { return new EventBasedExcelExtractor(poifsDir); } @@ -263,10 +293,10 @@ public class ExtractorFactory { /** * Returns an array of text extractors, one for each of - * the embeded documents in the file (if there are any). - * If there are no embeded documents, you'll get back an + * the embedded documents in the file (if there are any). + * If there are no embedded documents, you'll get back an * empty array. Otherwise, you'll get one open - * {@link POITextExtractor} for each embeded file. + * {@link POITextExtractor} for each embedded file. */ public static POITextExtractor[] getEmbededDocsTextExtractors(POIOLE2TextExtractor ext) throws IOException, InvalidFormatException, OpenXML4JException, XmlException { // All the embded directories we spotted diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java index e210be6f6..ccf57a655 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java @@ -29,6 +29,7 @@ import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.Hashtable; import java.util.List; @@ -581,6 +582,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { if (part.getContentType().equals(contentType)) retArr.add(part); } + Collections.sort(retArr); return retArr; } @@ -604,22 +606,31 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { retArr.add(part); } } + Collections.sort(retArr); return retArr; } + /** + * Retrieve parts by name + * + * @param namePattern + * The pattern for matching the names + * @return All parts associated to the specified content type, sorted + * in alphanumerically by the part-name + */ public List getPartsByName(final Pattern namePattern) { if (namePattern == null) { throw new IllegalArgumentException("name pattern must not be null"); } + Matcher matcher = namePattern.matcher(""); ArrayList result = new ArrayList(); for (PackagePart part : partList.values()) { PackagePartName partName = part.getPartName(); - String name = partName.getName(); - Matcher matcher = namePattern.matcher(name); - if (matcher.matches()) { + if (matcher.reset(partName.getName()).matches()) { result.add(part); } } + Collections.sort(result); return result; } @@ -727,7 +738,9 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { } } } - return new ArrayList(partList.values()); + ArrayList result = new ArrayList(partList.values()); + java.util.Collections.sort(result); + return result; } /** @@ -739,7 +752,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { * @param contentType * Part content type. * @return The newly created part. - * @throws InvalidFormatException + * @throws PartAlreadyExistsException * If rule M1.12 is not verified : Packages shall not contain * equivalent part names and package implementers shall neither * create nor recognize packages with equivalent part names. @@ -762,7 +775,7 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { * Specify if the existing relationship part, if any, logically * associated to the newly created part will be loaded. * @return The newly created part. - * @throws InvalidFormatException + * @throws PartAlreadyExistsException * If rule M1.12 is not verified : Packages shall not contain * equivalent part names and package implementers shall neither * create nor recognize packages with equivalent part names. @@ -1409,8 +1422,11 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { } catch (FileNotFoundException e) { throw new IOException(e.getLocalizedMessage()); } - this.save(fos); - fos.close(); + try { + this.save(fos); + } finally { + fos.close(); + } } /** @@ -1535,4 +1551,31 @@ public abstract class OPCPackage implements RelationshipSource, Closeable { } return success; } + + /** + * Add the specified part, and register its content type with the content + * type manager. + * + * @param part + * The part to add. + */ + public void registerPartAndContentType(PackagePart part) { + addPackagePart(part); + this.contentTypeManager.addContentType(part.getPartName(), part.getContentType()); + this.isDirty = true; + } + + /** + * Remove the specified part, and clear its content type from the content + * type manager. + * + * @param partName + * The part name of the part to remove. + */ + public void unregisterPartAndContentType(PackagePartName partName) { + removePart(partName); + this.contentTypeManager.removeContentType(partName); + this.isDirty = true; + } + } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java index 8b72770a7..8f961c933 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java @@ -30,11 +30,8 @@ import org.apache.poi.openxml4j.opc.internal.ContentType; /** * Provides a base class for parts stored in a Package. - * - * @author Julien Chable - * @version 0.9 */ -public abstract class PackagePart implements RelationshipSource { +public abstract class PackagePart implements RelationshipSource, Comparable { /** * This part's container. @@ -228,8 +225,13 @@ public abstract class PackagePart implements RelationshipSource { * Relationship unique id. * @return The newly created and added relationship * + * @throws InvalidOperationException + * If a writing operation is done on a read only package or + * invalid nested relations are created. * @throws InvalidFormatException * If the URI point to a relationship part URI. + * @throws IllegalArgumentException if targetPartName, targetMode + * or relationshipType are passed as null * @see org.apache.poi.openxml4j.opc.RelationshipSource#addRelationship(org.apache.poi.openxml4j.opc.PackagePartName, * org.apache.poi.openxml4j.opc.TargetMode, java.lang.String, java.lang.String) */ @@ -599,11 +601,14 @@ public abstract class PackagePart implements RelationshipSource { */ public void setContentType(String contentType) throws InvalidFormatException { - if (_container == null) - this._contentType = new ContentType(contentType); - else - throw new InvalidOperationException( - "You can't change the content type of a part."); + if (_container == null) { + _contentType = new ContentType(contentType); + } + else { + _container.unregisterPartAndContentType(_partName); + _contentType = new ContentType(contentType); + _container.registerPartAndContentType(this); + } } public OPCPackage getPackage() { @@ -645,6 +650,19 @@ public abstract class PackagePart implements RelationshipSource { + this._contentType.toString(); } + /** + * Compare based on the package part name, using a natural sort order + */ + @Override + public int compareTo(PackagePart other) + { + // NOTE could also throw a NullPointerException() if desired + if (other == null) + return -1; + + return PackagePartName.compare(this._partName, other._partName); + } + /*-------------- Abstract methods ------------- */ /** diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartName.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartName.java index 6f946a278..9ac6941bc 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartName.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartName.java @@ -17,6 +17,7 @@ package org.apache.poi.openxml4j.opc; +import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; @@ -428,19 +429,20 @@ public final class PackagePartName implements Comparable { } /** - * Compare two part name following the rule M1.12 : + * Compare two part names following the rule M1.12 : * * Part name equivalence is determined by comparing part names as * case-insensitive ASCII strings. Packages shall not contain equivalent * part names and package implementers shall neither create nor recognize * packages with equivalent part names. [M1.12] */ - public int compareTo(PackagePartName otherPartName) { - if (otherPartName == null) - return -1; - return this.partNameURI.toASCIIString().toLowerCase().compareTo( - otherPartName.partNameURI.toASCIIString().toLowerCase()); - } + @Override + public int compareTo(PackagePartName other) + { + // compare with natural sort order + return compare(this, other); + } + /** * Retrieves the extension of the part name if any. If there is no extension @@ -474,14 +476,17 @@ public final class PackagePartName implements Comparable { * packages with equivalent part names. [M1.12] */ @Override - public boolean equals(Object otherPartName) { - if (otherPartName == null - || !(otherPartName instanceof PackagePartName)) - return false; - return this.partNameURI.toASCIIString().toLowerCase().equals( - ((PackagePartName) otherPartName).partNameURI.toASCIIString() - .toLowerCase()); - } + public boolean equals(Object other) { + if (other instanceof PackagePartName) { + // String.equals() is compatible with our compareTo(), but cheaper + return this.partNameURI.toASCIIString().toLowerCase().equals + ( + ((PackagePartName) other).partNameURI.toASCIIString().toLowerCase() + ); + } else { + return false; + } + } @Override public int hashCode() { @@ -503,4 +508,106 @@ public final class PackagePartName implements Comparable { public URI getURI() { return this.partNameURI; } + + + /** + * A natural sort order for package part names, consistent with the + * requirements of {@code java.util.Comparator}, but simply implemented + * as a static method. + *

    + * For example, this sorts "file10.png" after "file2.png" (comparing the + * numerical portion), but sorts "File10.png" before "file2.png" + * (lexigraphical sort) + * + *

    + * When comparing part names, the rule M1.12 is followed: + * + * Part name equivalence is determined by comparing part names as + * case-insensitive ASCII strings. Packages shall not contain equivalent + * part names and package implementers shall neither create nor recognize + * packages with equivalent part names. [M1.12] + */ + public static int compare(PackagePartName obj1, PackagePartName obj2) + { + // NOTE could also throw a NullPointerException() if desired + if (obj1 == null) + { + // (null) == (null), (null) < (non-null) + return (obj2 == null ? 0 : -1); + } + else if (obj2 == null) + { + // (non-null) > (null) + return 1; + } + + return compare + ( + obj1.getURI().toASCIIString().toLowerCase(), + obj2.getURI().toASCIIString().toLowerCase() + ); + } + + + /** + * A natural sort order for strings, consistent with the + * requirements of {@code java.util.Comparator}, but simply implemented + * as a static method. + *

    + * For example, this sorts "file10.png" after "file2.png" (comparing the + * numerical portion), but sorts "File10.png" before "file2.png" + * (lexigraphical sort) + */ + public static int compare(String str1, String str2) + { + if (str1 == null) + { + // (null) == (null), (null) < (non-null) + return (str2 == null ? 0 : -1); + } + else if (str2 == null) + { + // (non-null) > (null) + return 1; + } + + int len1 = str1.length(); + int len2 = str2.length(); + for (int idx1 = 0, idx2 = 0; idx1 < len1 && idx2 < len2; /*nil*/) + { + char c1 = str1.charAt(idx1++); + char c2 = str2.charAt(idx2++); + + if (Character.isDigit(c1) && Character.isDigit(c2)) + { + int beg1 = idx1 - 1; // undo previous increment + while (idx1 < len1 && Character.isDigit(str1.charAt(idx1))) + { + ++idx1; + } + + int beg2 = idx2 - 1; // undo previous increment + while (idx2 < len2 && Character.isDigit(str2.charAt(idx2))) + { + ++idx2; + } + + // note: BigInteger for extra safety + int cmp = new BigInteger(str1.substring(beg1, idx1)).compareTo + ( + new BigInteger(str2.substring(beg2, idx2)) + ); + if (cmp != 0) return cmp; + } + else if (c1 != c2) + { + return (c1 - c2); + } + } + + return (len1 - len2); + } + } + +/* ************************************************************************** */ diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipTypes.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipTypes.java index 134e6a9fa..5d9801cd8 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipTypes.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipTypes.java @@ -19,14 +19,10 @@ package org.apache.poi.openxml4j.opc; /** * Relationship types. - * - * @author Julien Chable - * @version 0.2 */ public interface PackageRelationshipTypes { - - /** - * Core properties relationship type. + /** + * Core properties relationship type. * *

    * The standard specifies a source relations ship for the Core File Properties part as follows: @@ -37,71 +33,86 @@ public interface PackageRelationshipTypes { * http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties. *

    * See 2.1.33 Part 1 Section 15.2.11.1, Core File Properties Part in [MS-OE376].pdf - */ - String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; + */ + String CORE_PROPERTIES = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; /** * Core properties relationship type as defiend in ECMA 376. - */ + */ String CORE_PROPERTIES_ECMA376 = "http://schemas.openxmlformats.org/officedocument/2006/relationships/metadata/core-properties"; - /** - * Digital signature relationship type. - */ - String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature"; + /** + * Digital signature relationship type. + */ + String DIGITAL_SIGNATURE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/signature"; - /** - * Digital signature certificate relationship type. - */ - String DIGITAL_SIGNATURE_CERTIFICATE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/certificate"; + /** + * Digital signature certificate relationship type. + */ + String DIGITAL_SIGNATURE_CERTIFICATE = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/certificate"; - /** - * Digital signature origin relationship type. - */ - String DIGITAL_SIGNATURE_ORIGIN = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"; + /** + * Digital signature origin relationship type. + */ + String DIGITAL_SIGNATURE_ORIGIN = "http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin"; - /** - * Thumbnail relationship type. - */ - String THUMBNAIL = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; + /** + * Thumbnail relationship type. + */ + String THUMBNAIL = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; - /** - * Extended properties relationship type. - */ - String EXTENDED_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; + /** + * Extended properties relationship type. + */ + String EXTENDED_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; - /** - * Custom properties relationship type. - */ - String CUSTOM_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"; - - /** - * Core properties relationship type. - */ - String CORE_DOCUMENT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; + /** + * Extended properties relationship type for strict ooxml. + */ + String STRICT_EXTENDED_PROPERTIES = "http://purl.oclc.org/ooxml/officeDocument/relationships/extendedProperties"; - /** - * Custom XML relationship type. - */ - String CUSTOM_XML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"; + /** + * Custom properties relationship type. + */ + String CUSTOM_PROPERTIES = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"; - /** - * Image type. - */ - String IMAGE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; + /** + * Core document relationship type. + */ + String CORE_DOCUMENT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; + + /** + * Core document relationship type for strict ooxml. + */ + String STRICT_CORE_DOCUMENT = "http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument"; + + /** + * Custom XML relationship type. + */ + String CUSTOM_XML = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"; + + /** + * Image type. + */ + String IMAGE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; /** * Hyperlink type. */ String HYPERLINK_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"; - /** - * Style type. - */ - String STYLE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; - - /** - * External Link to another Document - */ - String EXTERNAL_LINK_PATH = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath"; + /** + * Style type. + */ + String STYLE_PART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; + + /** + * External Link to another Document + */ + String EXTERNAL_LINK_PATH = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/externalLinkPath"; + + /** + * Visio 2010 VSDX equivalent of package {@link #CORE_DOCUMENT} + */ + String VISIO_CORE_DOCUMENT = "http://schemas.microsoft.com/visio/2010/relationships/document"; } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java index 62f26b754..8937f8e53 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java @@ -41,6 +41,8 @@ import org.apache.poi.openxml4j.opc.internal.marshallers.ZipPartMarshaller; import org.apache.poi.openxml4j.util.ZipEntrySource; import org.apache.poi.openxml4j.util.ZipFileZipEntrySource; import org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource; +import org.apache.poi.openxml4j.util.ZipSecureFile; +import org.apache.poi.openxml4j.util.ZipSecureFile.ThresholdInputStream; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.TempFile; @@ -85,9 +87,9 @@ public final class ZipPackage extends Package { @SuppressWarnings("deprecation") ZipPackage(InputStream in, PackageAccess access) throws IOException { super(access); - this.zipArchive = new ZipInputStreamZipEntrySource( - new ZipInputStream(in) - ); + InputStream zis = new ZipInputStream(in); + ThresholdInputStream tis = ZipSecureFile.addThreshold(zis); + this.zipArchive = new ZipInputStreamZipEntrySource(tis); } /** @@ -443,7 +445,9 @@ public final class ZipPackage extends Package { if (this.getPartsByRelationshipType(PackageRelationshipTypes.CORE_PROPERTIES).size() == 0 && this.getPartsByRelationshipType(PackageRelationshipTypes.CORE_PROPERTIES_ECMA376).size() == 0 ) { logger.log(POILogger.DEBUG,"Save core properties part"); - + + // Ensure that core properties are added if missing + getPackageProperties(); // Add core properties to part list ... addPackagePart(this.packageProperties); // ... and to add its relationship ... diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java index 9598b05cb..408fa416f 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java @@ -29,6 +29,7 @@ import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; import org.apache.poi.openxml4j.opc.ZipPackage; +import org.apache.poi.openxml4j.util.ZipSecureFile; public final class ZipHelper { @@ -154,7 +155,7 @@ public final class ZipHelper { return null; } - return new ZipFile(file); + return new ZipSecureFile(file); } /** @@ -171,6 +172,6 @@ public final class ZipHelper { return null; } - return new ZipFile(f); + return new ZipSecureFile(f); } } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/PackagePropertiesMarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/PackagePropertiesMarshaller.java index ca549f91f..76e292bea 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/PackagePropertiesMarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/PackagePropertiesMarshaller.java @@ -34,15 +34,11 @@ import org.w3c.dom.Element; /** * Package properties marshaller. - * - * @author CDubet, Julien Chable */ public class PackagePropertiesMarshaller implements PartMarshaller { - - private final static Namespace namespaceDC, namespaceCoreProperties, namespaceDcTerms, namespaceXSI; static { - final XMLEventFactory f = XMLEventFactory.newFactory(); + final XMLEventFactory f = XMLEventFactory.newInstance(); namespaceDC = f.createNamespace("dc", PackagePropertiesPart.NAMESPACE_DC_URI); namespaceCoreProperties = f.createNamespace("cp", PackagePropertiesPart.NAMESPACE_CP_URI); namespaceDcTerms = f.createNamespace("dcterms", PackagePropertiesPart.NAMESPACE_DCTERMS_URI); diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java index f7f334c75..7d72212cd 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java @@ -26,6 +26,8 @@ import java.util.Iterator; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import org.apache.poi.openxml4j.util.ZipSecureFile.ThresholdInputStream; + /** * Provides a way to get at all the ZipEntries * from a ZipInputStream, as many times as required. @@ -43,7 +45,7 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource { * We'll then eat lots of memory, but be able to * work with the entries at-will. */ - public ZipInputStreamZipEntrySource(ZipInputStream inp) throws IOException { + public ZipInputStreamZipEntrySource(ThresholdInputStream inp) throws IOException { zipEntries = new ArrayList(); boolean going = true; @@ -105,7 +107,7 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource { public static class FakeZipEntry extends ZipEntry { private byte[] data; - public FakeZipEntry(ZipEntry entry, ZipInputStream inp) throws IOException { + public FakeZipEntry(ZipEntry entry, InputStream inp) throws IOException { super(entry.getName()); // Grab the de-compressed contents for later diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java new file mode 100644 index 000000000..60b31ee27 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java @@ -0,0 +1,215 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.openxml4j.util; + +import java.io.File; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.lang.reflect.Field; +import java.nio.charset.Charset; +import java.util.zip.InflaterInputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; + +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * This class wraps a {@link ZipFile} in order to check the + * entries for zip bombs + * while reading the archive. + * If a {@link ZipInputStream} is directly used, the wrapper + * can be applied via {@link #addThreshold(InputStream)}. + * The alert limits can be globally defined via {@link #setMaxEntrySize(long)} + * and {@link #setMinInflateRatio(double)}. + */ +public class ZipSecureFile extends ZipFile { + private static POILogger logger = POILogFactory.getLogger(ZipSecureFile.class); + + private static double MIN_INFLATE_RATIO = 0.01d; + private static long MAX_ENTRY_SIZE = 0xFFFFFFFFl; + + /** + * Sets the ratio between de- and inflated bytes to detect zipbomb. + * It defaults to 1% (= 0.01d), i.e. when the compression is better than + * 1% for any given read package part, the parsing will fail + * + * @param ratio the ratio between de- and inflated bytes to detect zipbomb + */ + public static void setMinInflateRatio(double ratio) { + MIN_INFLATE_RATIO = ratio; + } + + /** + * Sets the maximum file size of a single zip entry. It defaults to 4GB, + * i.e. the 32-bit zip format maximum. + * + * @param maxEntrySize the max. file size of a single zip entry + */ + public static void setMaxEntrySize(long maxEntrySize) { + if (maxEntrySize < 0 || maxEntrySize > 0xFFFFFFFFl) { + throw new IllegalArgumentException("Max entry size is bounded [0-4GB]."); + } + MAX_ENTRY_SIZE = maxEntrySize; + } + + public ZipSecureFile(File file, int mode) throws IOException { + super(file, mode); + } + + public ZipSecureFile(File file) throws ZipException, IOException { + super(file); + } + + public ZipSecureFile(String name) throws IOException { + super(name); + } + + /** + * Returns an input stream for reading the contents of the specified + * zip file entry. + * + *

    Closing this ZIP file will, in turn, close all input + * streams that have been returned by invocations of this method. + * + * @param entry the zip file entry + * @return the input stream for reading the contents of the specified + * zip file entry. + * @throws ZipException if a ZIP format error has occurred + * @throws IOException if an I/O error has occurred + * @throws IllegalStateException if the zip file has been closed + */ + public InputStream getInputStream(ZipEntry entry) throws IOException { + InputStream zipIS = super.getInputStream(entry); + return addThreshold(zipIS); + } + + public static ThresholdInputStream addThreshold(InputStream zipIS) throws IOException { + ThresholdInputStream newInner; + if (zipIS instanceof InflaterInputStream) { + try { + Field f = FilterInputStream.class.getDeclaredField("in"); + f.setAccessible(true); + InputStream oldInner = (InputStream)f.get(zipIS); + newInner = new ThresholdInputStream(oldInner, null); + f.set(zipIS, newInner); + } catch (Exception ex) { + logger.log(POILogger.WARN, "SecurityManager doesn't allow manipulation via reflection for zipbomb detection - continue with original input stream", ex); + newInner = null; + } + } else { + // the inner stream is a ZipFileInputStream, i.e. the data wasn't compressed + newInner = null; + } + + return new ThresholdInputStream(zipIS, newInner); + } + + public static class ThresholdInputStream extends PushbackInputStream { + long counter = 0; + ThresholdInputStream cis; + + public ThresholdInputStream(InputStream is, ThresholdInputStream cis) { + super(is,1); + this.cis = cis; + } + + public int read() throws IOException { + int b = in.read(); + if (b > -1) advance(1); + return b; + } + + public int read(byte b[], int off, int len) throws IOException { + int cnt = in.read(b, off, len); + if (cnt > -1) advance(cnt); + return cnt; + + } + + public long skip(long n) throws IOException { + counter = 0; + return in.skip(n); + } + + public synchronized void reset() throws IOException { + counter = 0; + in.reset(); + } + + public void advance(int advance) throws IOException { + counter += advance; + // check the file size first, in case we are working on uncompressed streams + if (counter < MAX_ENTRY_SIZE) { + if (cis == null) return; + double ratio = (double)cis.counter/(double)counter; + if (ratio > MIN_INFLATE_RATIO) return; + } + throw new IOException("Zip bomb detected! Exiting."); + } + + public ZipEntry getNextEntry() throws IOException { + if (!(in instanceof ZipInputStream)) { + throw new UnsupportedOperationException("underlying stream is not a ZipInputStream"); + } + counter = 0; + return ((ZipInputStream)in).getNextEntry(); + } + + public void closeEntry() throws IOException { + if (!(in instanceof ZipInputStream)) { + throw new UnsupportedOperationException("underlying stream is not a ZipInputStream"); + } + counter = 0; + ((ZipInputStream)in).closeEntry(); + } + + public void unread(int b) throws IOException { + if (!(in instanceof PushbackInputStream)) { + throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream"); + } + if (--counter < 0) counter = 0; + ((PushbackInputStream)in).unread(b); + } + + public void unread(byte[] b, int off, int len) throws IOException { + if (!(in instanceof PushbackInputStream)) { + throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream"); + } + counter -= len; + if (--counter < 0) counter = 0; + ((PushbackInputStream)in).unread(b, off, len); + } + + public int available() throws IOException { + return in.available(); + } + + public boolean markSupported() { + return in.markSupported(); + } + + public synchronized void mark(int readlimit) { + in.mark(readlimit); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java index 05499685f..3af78128c 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java @@ -279,7 +279,7 @@ public class AgileDecryptor extends Decryptor { } public InputStream getDataStream(DirectoryNode dir) throws IOException, GeneralSecurityException { - DocumentInputStream dis = dir.createDocumentInputStream("EncryptedPackage"); + DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY); _length = dis.readLong(); ChunkedCipherInputStream cipherStream = new AgileCipherInputStream(dis, _length); diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java index 51ced4c2c..c6d307259 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java @@ -33,6 +33,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.security.GeneralSecurityException; import java.security.MessageDigest; @@ -242,12 +243,15 @@ public class AgileEncryptor extends Encryptor { LittleEndian.putLong(buf, 0, oleStreamSize); integrityMD.update(buf, 0, LittleEndian.LONG_SIZE); - FileInputStream fis = new FileInputStream(tmpFile); - int readBytes; - while ((readBytes = fis.read(buf)) != -1) { - integrityMD.update(buf, 0, readBytes); + InputStream fis = new FileInputStream(tmpFile); + try { + int readBytes; + while ((readBytes = fis.read(buf)) != -1) { + integrityMD.update(buf, 0, readBytes); + } + } finally { + fis.close(); } - fis.close(); byte hmacValue[] = integrityMD.doFinal(); diff --git a/src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java b/src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java index de847fd19..dfdf3f92e 100644 --- a/src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java +++ b/src/ooxml/java/org/apache/poi/ss/usermodel/WorkbookFactory.java @@ -21,106 +21,279 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.PushbackInputStream; +import java.security.GeneralSecurityException; +import org.apache.poi.EmptyFileException; +import org.apache.poi.EncryptedDocumentException; import org.apache.poi.POIXMLDocument; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.OfficeXmlFileException; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * Factory for creating the appropriate kind of Workbook - * (be it {@link HSSFWorkbook} or {@link XSSFWorkbook}), + * (be it {@link HSSFWorkbook} or {@link XSSFWorkbook}), * by auto-detecting from the supplied input. */ public class WorkbookFactory { /** * Creates a HSSFWorkbook from the given POIFSFileSystem - *

    Note that in order to properly release resources the + *

    Note that in order to properly release resources the * Workbook should be closed after use. */ public static Workbook create(POIFSFileSystem fs) throws IOException { return new HSSFWorkbook(fs); } - + /** * Creates a HSSFWorkbook from the given NPOIFSFileSystem - *

    Note that in order to properly release resources the + *

    Note that in order to properly release resources the * Workbook should be closed after use. */ public static Workbook create(NPOIFSFileSystem fs) throws IOException { - return new HSSFWorkbook(fs.getRoot(), true); + try { + return create(fs, null); + } catch (InvalidFormatException e) { + // Special case of OOXML-in-POIFS which is broken + throw new IOException(e); + } } - + + /** + * Creates a Workbook from the given NPOIFSFileSystem, which may + * be password protected + * + * @param fs The {@link NPOIFSFileSystem} to read the document from + * @param password The password that should be used or null if no password is necessary. + * + * @return The created Workbook + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook} + */ + private static Workbook create(NPOIFSFileSystem fs, String password) throws IOException, InvalidFormatException { + DirectoryNode root = fs.getRoot(); + + // Encrypted OOXML files go inside OLE2 containers, is this one? + if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) { + EncryptionInfo info = new EncryptionInfo(fs); + Decryptor d = Decryptor.getInstance(info); + + boolean passwordCorrect = false; + InputStream stream = null; + try { + if (password != null && d.verifyPassword(password)) { + passwordCorrect = true; + } + if (!passwordCorrect && d.verifyPassword(Decryptor.DEFAULT_PASSWORD)) { + passwordCorrect = true; + } + if (passwordCorrect) { + stream = d.getDataStream(root); + } + } catch (GeneralSecurityException e) { + throw new IOException(e); + } + + if (! passwordCorrect) { + if (password != null) + throw new EncryptedDocumentException("Password incorrect"); + else + throw new EncryptedDocumentException("The supplied spreadsheet is protected, but no password was supplied"); + } + + OPCPackage pkg = OPCPackage.open(stream); + return create(pkg); + } + + // If we get here, it isn't an encrypted XLSX file + // So, treat it as a regular HSSF XLS one + if (password != null) { + Biff8EncryptionKey.setCurrentUserPassword(password); + } + Workbook wb = new HSSFWorkbook(root, true); + Biff8EncryptionKey.setCurrentUserPassword(null); + return wb; + } + /** * Creates a XSSFWorkbook from the given OOXML Package - *

    Note that in order to properly release resources the - * Workbook should be closed after use. + * + *

    Note that in order to properly release resources the + * Workbook should be closed after use.

    + * + * @param pkg The {@link OPCPackage} opened for reading data. + * + * @return The created Workbook + * + * @throws IOException if an error occurs while reading the data */ public static Workbook create(OPCPackage pkg) throws IOException { return new XSSFWorkbook(pkg); } - + /** * Creates the appropriate HSSFWorkbook / XSSFWorkbook from * the given InputStream. + * *

    Your input stream MUST either support mark/reset, or - * be wrapped as a {@link PushbackInputStream}! Note that - * using an {@link InputStream} has a higher memory footprint - * than using a {@link File}.

    - *

    Note that in order to properly release resources the - * Workbook should be closed after use. + * be wrapped as a {@link PushbackInputStream}! Note that + * using an {@link InputStream} has a higher memory footprint + * than using a {@link File}.

    + * + *

    Note that in order to properly release resources the + * Workbook should be closed after use. Note also that loading + * from an InputStream requires more memory than loading + * from a File, so prefer {@link #create(File)} where possible. + * + * @param inp The {@link InputStream} to read data from. + * + * @return The created Workbook + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook} + * @throws EncryptedDocumentException If the workbook given is password protected */ - public static Workbook create(InputStream inp) throws IOException, InvalidFormatException { + public static Workbook create(InputStream inp) throws IOException, InvalidFormatException, EncryptedDocumentException { + return create(inp, null); + } + + /** + * Creates the appropriate HSSFWorkbook / XSSFWorkbook from + * the given InputStream, which may be password protected. + *

    Your input stream MUST either support mark/reset, or + * be wrapped as a {@link PushbackInputStream}! Note that + * using an {@link InputStream} has a higher memory footprint + * than using a {@link File}.

    + * + *

    Note that in order to properly release resources the + * Workbook should be closed after use. Note also that loading + * from an InputStream requires more memory than loading + * from a File, so prefer {@link #create(File)} where possible.

    + * + * @param inp The {@link InputStream} to read data from. + * @param password The password that should be used or null if no password is necessary. + * + * @return The created Workbook + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook} + * @throws EncryptedDocumentException If the wrong password is given for a protected file + * @throws EmptyFileException If an empty stream is given + */ + public static Workbook create(InputStream inp, String password) throws IOException, InvalidFormatException, EncryptedDocumentException { // If clearly doesn't do mark/reset, wrap up if (! inp.markSupported()) { inp = new PushbackInputStream(inp, 8); } - if (POIFSFileSystem.hasPOIFSHeader(inp)) { - return new HSSFWorkbook(inp); + // Ensure that there is at least some data there + byte[] header8 = IOUtils.peekFirst8Bytes(inp); + + // Try to create + if (NPOIFSFileSystem.hasPOIFSHeader(header8)) { + NPOIFSFileSystem fs = new NPOIFSFileSystem(inp); + return create(fs, password); } if (POIXMLDocument.hasOOXMLHeader(inp)) { return new XSSFWorkbook(OPCPackage.open(inp)); } throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); } - + /** * Creates the appropriate HSSFWorkbook / XSSFWorkbook from * the given File, which must exist and be readable. - *

    Note that in order to properly release resources the + *

    Note that in order to properly release resources the * Workbook should be closed after use. + * + * @param file The file to read data from. + * + * @return The created Workbook + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook} + * @throws EncryptedDocumentException If the workbook given is password protected */ - public static Workbook create(File file) throws IOException, InvalidFormatException { + public static Workbook create(File file) throws IOException, InvalidFormatException, EncryptedDocumentException { + return create(file, null); + } + + /** + * Creates the appropriate HSSFWorkbook / XSSFWorkbook from + * the given File, which must exist and be readable, and + * may be password protected + *

    Note that in order to properly release resources the + * Workbook should be closed after use. + * + * @param file The file to read data from. + * @param password The password that should be used or null if no password is necessary. + * + * @return The created Workbook + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook} + * @throws EncryptedDocumentException If the wrong password is given for a protected file + * @throws EmptyFileException If an empty stream is given + */ + public static Workbook create(File file, String password) throws IOException, InvalidFormatException, EncryptedDocumentException { + return create(file, password, false); + } + + /** + * Creates the appropriate HSSFWorkbook / XSSFWorkbook from + * the given File, which must exist and be readable, and + * may be password protected + *

    Note that in order to properly release resources the + * Workbook should be closed after use. + * + * @param file The file to read data from. + * @param password The password that should be used or null if no password is necessary. + * @param readOnly If the Workbook should be opened in read-only mode to avoid writing back + * changes when the document is closed. + * + * @return The created Workbook + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link Workbook} + * @throws EncryptedDocumentException If the wrong password is given for a protected file + * @throws EmptyFileException If an empty stream is given + */ + public static Workbook create(File file, String password, boolean readOnly) throws IOException, InvalidFormatException, EncryptedDocumentException { if (! file.exists()) { throw new FileNotFoundException(file.toString()); } try { - @SuppressWarnings("resource") - NPOIFSFileSystem fs = new NPOIFSFileSystem(file); - return new HSSFWorkbook(fs.getRoot(), true); + NPOIFSFileSystem fs = new NPOIFSFileSystem(file, readOnly); + return create(fs, password); } catch(OfficeXmlFileException e) { // opening as .xls failed => try opening as .xlsx - OPCPackage pkg = OPCPackage.open(file); + OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE); try { return new XSSFWorkbook(pkg); } catch (IOException ioe) { // ensure that file handles are closed (use revert() to not re-write the file) pkg.revert(); //pkg.close(); - + // rethrow exception throw ioe; } catch (IllegalArgumentException ioe) { - // ensure that file handles are closed (use revert() to not re-write the file) + // ensure that file handles are closed (use revert() to not re-write the file) pkg.revert(); //pkg.close(); - + // rethrow exception throw ioe; } diff --git a/src/ooxml/java/org/apache/poi/util/OOXMLLite.java b/src/ooxml/java/org/apache/poi/util/OOXMLLite.java index 3b8dc3220..0503dfa76 100644 --- a/src/ooxml/java/org/apache/poi/util/OOXMLLite.java +++ b/src/ooxml/java/org/apache/poi/util/OOXMLLite.java @@ -32,14 +32,12 @@ import java.util.Map; import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.regex.Pattern; - -import junit.framework.TestCase; - -import org.junit.Test; -import org.junit.internal.TextListener; -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; +import java.util.regex.Pattern; + +import junit.framework.TestCase; +import org.junit.Test; +import org.junit.internal.TextListener; +import org.junit.runner.JUnitCore;import org.junit.runner.Result; /** * Build a 'lite' version of the ooxml-schemas.jar diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRenderer.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRenderer.java index 6e2633515..7153bc86a 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRenderer.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRenderer.java @@ -99,6 +99,10 @@ public class XSLFImageRenderer { } catch (Exception e) { return false; } + + if(img == null) { + return false; + } int iw = img.getWidth(); int ih = img.getHeight(); diff --git a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java index 7e449dad3..a3e04eb24 100644 --- a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java +++ b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java @@ -19,13 +19,13 @@ package org.apache.poi.xssf.dev; import java.io.File; import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.apache.poi.openxml4j.opc.internal.ZipHelper; +import org.apache.poi.util.IOUtils; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; @@ -39,8 +39,12 @@ public final class XSSFDump { public static void main(String[] args) throws Exception { for (int i = 0; i < args.length; i++) { System.out.println("Dumping " + args[i]); - ZipFile zip = new ZipFile(args[i]); - dump(zip); + ZipFile zip = ZipHelper.openZipFile(args[i]); + try { + dump(zip); + } finally { + zip.close(); + } } } @@ -49,6 +53,7 @@ public final class XSSFDump { int sep = zipname.lastIndexOf('.'); File root = new File(zipname.substring(0, sep)); root.mkdir(); + System.out.println("Dupming to directory " + root); Enumeration en = zip.entries(); while(en.hasMoreElements()){ @@ -61,30 +66,24 @@ public final class XSSFDump { } File f = new File(root, entry.getName()); - FileOutputStream out = new FileOutputStream(f); - - if(entry.getName().endsWith(".xml") || entry.getName().endsWith(".vml") || entry.getName().endsWith(".rels")){ - try { - XmlObject xml = XmlObject.Factory.parse(zip.getInputStream(entry)); - XmlOptions options = new XmlOptions(); - options.setSavePrettyPrint(); - xml.save(out, options); - } catch (Exception e){ - System.err.println("Failed to parse " + entry.getName() + ", dumping raw content"); - dump(zip.getInputStream(entry), out); + OutputStream out = new FileOutputStream(f); + try { + if(entry.getName().endsWith(".xml") || entry.getName().endsWith(".vml") || entry.getName().endsWith(".rels")){ + try { + XmlObject xml = XmlObject.Factory.parse(zip.getInputStream(entry)); + XmlOptions options = new XmlOptions(); + options.setSavePrettyPrint(); + xml.save(out, options); + } catch (Exception e){ + System.err.println("Failed to parse " + entry.getName() + ", dumping raw content"); + IOUtils.copy(zip.getInputStream(entry), out); + } + } else { + IOUtils.copy(zip.getInputStream(entry), out); } - } else { - dump(zip.getInputStream(entry), out); + } finally { + out.close(); } - out.close(); - } } - - protected static void dump(InputStream is, OutputStream out) throws IOException{ - int pos; - byte[] chunk = new byte[2048]; - while((pos = is.read(chunk)) > 0) out.write(chunk, 0, pos); - - } } diff --git a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java index 767742687..227441859 100644 --- a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java +++ b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java @@ -96,6 +96,7 @@ public class XSSFSheetXMLHandler extends DefaultHandler { private String formatString; private final DataFormatter formatter; private int rowNum; + private int nextRowNum; // some sheets do not have rowNums, Excel can read them so we should try to handle them correctly as well private String cellRef; private boolean formulasNotResults; @@ -240,7 +241,12 @@ public class XSSFSheetXMLHandler extends DefaultHandler { headerFooter.setLength(0); } else if("row".equals(name)) { - rowNum = Integer.parseInt(attributes.getValue("r")) - 1; + String rowNumStr = attributes.getValue("r"); + if(rowNumStr != null) { + rowNum = Integer.parseInt(rowNumStr) - 1; + } else { + rowNum = nextRowNum; + } output.startRow(rowNum); } // c => cell @@ -343,7 +349,7 @@ public class XSSFSheetXMLHandler extends DefaultHandler { case NUMBER: String n = value.toString(); - if (this.formatString != null) + if (this.formatString != null && n.length() > 0) thisStr = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, this.formatString); else thisStr = n; @@ -370,6 +376,9 @@ public class XSSFSheetXMLHandler extends DefaultHandler { // Finish up the row output.endRow(rowNum); + + // some sheets do not have rowNum set in the XML, Excel can read them so we should try to read them as well + nextRowNum = rowNum + 1; } else if ("sheetData".equals(name)) { // Handle any "missing" cells which had comments attached checkForEmptyCellComments(EmptyCellCommentsCheckType.END_OF_SHEET_DATA); diff --git a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExcelExtractor.java b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExcelExtractor.java index 6f43ba126..39ef5be8a 100644 --- a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExcelExtractor.java +++ b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExcelExtractor.java @@ -80,7 +80,11 @@ public class XSSFExcelExtractor extends POIXMLTextExtractor } POIXMLTextExtractor extractor = new XSSFExcelExtractor(args[0]); - System.out.println(extractor.getText()); + try { + System.out.println(extractor.getText()); + } finally { + extractor.close(); + } } /** @@ -237,7 +241,7 @@ public class XSSFExcelExtractor extends POIXMLTextExtractor if (type == Cell.CELL_TYPE_NUMERIC) { CellStyle cs = cell.getCellStyle(); - if (cs.getDataFormatString() != null) { + if (cs != null && cs.getDataFormatString() != null) { text.append(formatter.formatRawCellContents( cell.getNumericCellValue(), cs.getDataFormat(), cs.getDataFormatString() )); diff --git a/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java b/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java index 53d1b7651..3937e3eea 100644 --- a/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java @@ -22,7 +22,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -30,6 +30,7 @@ import java.util.Map.Entry; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.ss.usermodel.FontFamily; import org.apache.poi.ss.usermodel.FontScheme; @@ -59,91 +60,93 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument; /** * Table of styles shared across all sheets in a workbook. - * - * @author ugo */ public class StylesTable extends POIXMLDocumentPart { - private final Map numberFormats = new LinkedHashMap(); - private final List fonts = new ArrayList(); - private final List fills = new ArrayList(); - private final List borders = new ArrayList(); - private final List styleXfs = new ArrayList(); - private final List xfs = new ArrayList(); + private final Map numberFormats = new HashMap(); + private final boolean[] usedNumberFormats = new boolean[SpreadsheetVersion.EXCEL2007.getMaxCellStyles()]; + private final List fonts = new ArrayList(); + private final List fills = new ArrayList(); + private final List borders = new ArrayList(); + private final List styleXfs = new ArrayList(); + private final List xfs = new ArrayList(); - private final List dxfs = new ArrayList(); + private final List dxfs = new ArrayList(); - /** - * The first style id available for use as a custom style - */ - public static final int FIRST_CUSTOM_STYLE_ID = BuiltinFormats.FIRST_USER_DEFINED_FORMAT_INDEX + 1; + /** + * The first style id available for use as a custom style + */ + public static final int FIRST_CUSTOM_STYLE_ID = BuiltinFormats.FIRST_USER_DEFINED_FORMAT_INDEX + 1; + private static final int MAXIMUM_STYLE_ID = SpreadsheetVersion.EXCEL2007.getMaxCellStyles(); - private StyleSheetDocument doc; - private ThemesTable theme; + private StyleSheetDocument doc; + private ThemesTable theme; - /** - * Create a new, empty StylesTable - */ - public StylesTable() { - super(); - doc = StyleSheetDocument.Factory.newInstance(); - doc.addNewStyleSheet(); - // Initialization required in order to make the document readable by MSExcel - initialize(); - } + /** + * Create a new, empty StylesTable + */ + public StylesTable() { + super(); + doc = StyleSheetDocument.Factory.newInstance(); + doc.addNewStyleSheet(); + // Initialization required in order to make the document readable by MSExcel + initialize(); + } - public StylesTable(PackagePart part, PackageRelationship rel) throws IOException { - super(part, rel); - readFrom(part.getInputStream()); - } + public StylesTable(PackagePart part, PackageRelationship rel) throws IOException { + super(part, rel); + readFrom(part.getInputStream()); + } - public ThemesTable getTheme() { + public ThemesTable getTheme() { return theme; } public void setTheme(ThemesTable theme) { this.theme = theme; - + // Pass the themes table along to things which need to // know about it, but have already been created by now for(XSSFFont font : fonts) { - font.setThemesTable(theme); + font.setThemesTable(theme); } for(XSSFCellBorder border : borders) { - border.setThemesTable(theme); + border.setThemesTable(theme); } } - /** - * Read this shared styles table from an XML file. - * - * @param is The input stream containing the XML document. - * @throws IOException if an error occurs while reading. - */ + /** + * Read this shared styles table from an XML file. + * + * @param is The input stream containing the XML document. + * @throws IOException if an error occurs while reading. + */ @SuppressWarnings("deprecation") //YK: getXYZArray() array accessors are deprecated in xmlbeans with JDK 1.5 support - protected void readFrom(InputStream is) throws IOException { - try { - doc = StyleSheetDocument.Factory.parse(is); + protected void readFrom(InputStream is) throws IOException { + try { + doc = StyleSheetDocument.Factory.parse(is); CTStylesheet styleSheet = doc.getStyleSheet(); // Grab all the different bits we care about - CTNumFmts ctfmts = styleSheet.getNumFmts(); + CTNumFmts ctfmts = styleSheet.getNumFmts(); if( ctfmts != null){ for (CTNumFmt nfmt : ctfmts.getNumFmtArray()) { - numberFormats.put((int)nfmt.getNumFmtId(), nfmt.getFormatCode()); + int formatId = (int)nfmt.getNumFmtId(); + numberFormats.put(formatId, nfmt.getFormatCode()); + usedNumberFormats[formatId] = true; } } CTFonts ctfonts = styleSheet.getFonts(); if(ctfonts != null){ - int idx = 0; - for (CTFont font : ctfonts.getFontArray()) { - // Create the font and save it. Themes Table supplied later - XSSFFont f = new XSSFFont(font, idx); - fonts.add(f); - idx++; - } - } + int idx = 0; + for (CTFont font : ctfonts.getFontArray()) { + // Create the font and save it. Themes Table supplied later + XSSFFont f = new XSSFFont(font, idx); + fonts.add(f); + idx++; + } + } CTFills ctfills = styleSheet.getFills(); if(ctfills != null){ for (CTFill fill : ctfills.getFillArray()) { @@ -165,401 +168,409 @@ public class StylesTable extends POIXMLDocumentPart { if(cellStyleXfs != null) styleXfs.addAll(Arrays.asList(cellStyleXfs.getXfArray())); CTDxfs styleDxfs = styleSheet.getDxfs(); - if(styleDxfs != null) dxfs.addAll(Arrays.asList(styleDxfs.getDxfArray())); + if(styleDxfs != null) dxfs.addAll(Arrays.asList(styleDxfs.getDxfArray())); - } catch (XmlException e) { - throw new IOException(e.getLocalizedMessage()); - } - } + } catch (XmlException e) { + throw new IOException(e.getLocalizedMessage()); + } + } - // =========================================================== - // Start of style related getters and setters - // =========================================================== + // =========================================================== + // Start of style related getters and setters + // =========================================================== - public String getNumberFormatAt(int idx) { - return numberFormats.get(idx); - } + public String getNumberFormatAt(int idx) { + return numberFormats.get(idx); + } - public int putNumberFormat(String fmt) { - if (numberFormats.containsValue(fmt)) { - // Find the key, and return that - for(Integer key : numberFormats.keySet() ) { - if(numberFormats.get(key).equals(fmt)) { - return key; - } - } - throw new IllegalStateException("Found the format, but couldn't figure out where - should never happen!"); - } + public int putNumberFormat(String fmt) { + if (numberFormats.containsValue(fmt)) { + // Find the key, and return that + for (Entry numFmt : numberFormats.entrySet()) { + if(numFmt.getValue().equals(fmt)) { + return numFmt.getKey(); + } + } + throw new IllegalStateException("Found the format, but couldn't figure out where - should never happen!"); + } - // Find a spare key, and add that - int newKey = FIRST_CUSTOM_STYLE_ID; - while(numberFormats.containsKey(newKey)) { - newKey++; - } - numberFormats.put(newKey, fmt); - return newKey; - } + // Find a spare key, and add that + for (int i=FIRST_CUSTOM_STYLE_ID; i 0) { - styleXfId = (int) xfs.get(idx).getXfId(); - } + public XSSFCellStyle getStyleAt(int idx) { + int styleXfId = 0; - return new XSSFCellStyle(idx, styleXfId, this, theme); - } - public int putStyle(XSSFCellStyle style) { - CTXf mainXF = style.getCoreXf(); + // 0 is the empty default + if(xfs.get(idx).getXfId() > 0) { + styleXfId = (int) xfs.get(idx).getXfId(); + } - if(! xfs.contains(mainXF)) { - xfs.add(mainXF); - } - return xfs.indexOf(mainXF); - } + return new XSSFCellStyle(idx, styleXfId, this, theme); + } + public int putStyle(XSSFCellStyle style) { + CTXf mainXF = style.getCoreXf(); - public XSSFCellBorder getBorderAt(int idx) { - return borders.get(idx); - } + if(! xfs.contains(mainXF)) { + xfs.add(mainXF); + } + return xfs.indexOf(mainXF); + } - public int putBorder(XSSFCellBorder border) { - int idx = borders.indexOf(border); - if (idx != -1) { - return idx; - } - borders.add(border); - border.setThemesTable(theme); - return borders.size() - 1; - } + public XSSFCellBorder getBorderAt(int idx) { + return borders.get(idx); + } - public XSSFCellFill getFillAt(int idx) { - return fills.get(idx); - } + public int putBorder(XSSFCellBorder border) { + int idx = borders.indexOf(border); + if (idx != -1) { + return idx; + } + borders.add(border); + border.setThemesTable(theme); + return borders.size() - 1; + } - public List getBorders(){ - return borders; - } + public XSSFCellFill getFillAt(int idx) { + return fills.get(idx); + } - public List getFills(){ - return fills; - } + public List getBorders(){ + return borders; + } - public List getFonts(){ - return fonts; - } + public List getFills(){ + return fills; + } - public Map getNumberFormats(){ - return numberFormats; - } + public List getFonts(){ + return fonts; + } - public int putFill(XSSFCellFill fill) { - int idx = fills.indexOf(fill); - if (idx != -1) { - return idx; - } - fills.add(fill); - return fills.size() - 1; - } + public Map getNumberFormats(){ + return numberFormats; + } - public CTXf getCellXfAt(int idx) { - return xfs.get(idx); - } - public int putCellXf(CTXf cellXf) { - xfs.add(cellXf); - return xfs.size(); - } - public void replaceCellXfAt(int idx, CTXf cellXf) { - xfs.set(idx, cellXf); - } + public int putFill(XSSFCellFill fill) { + int idx = fills.indexOf(fill); + if (idx != -1) { + return idx; + } + fills.add(fill); + return fills.size() - 1; + } - public CTXf getCellStyleXfAt(int idx) { - return idx < styleXfs.size() ? styleXfs.get(idx) : null; - } - public int putCellStyleXf(CTXf cellStyleXf) { - styleXfs.add(cellStyleXf); - return styleXfs.size(); - } - public void replaceCellStyleXfAt(int idx, CTXf cellStyleXf) { - styleXfs.set(idx, cellStyleXf); - } - - /** - * get the size of cell styles - */ - public int getNumCellStyles(){ + public CTXf getCellXfAt(int idx) { + return xfs.get(idx); + } + public int putCellXf(CTXf cellXf) { + xfs.add(cellXf); + return xfs.size(); + } + public void replaceCellXfAt(int idx, CTXf cellXf) { + xfs.set(idx, cellXf); + } + + public CTXf getCellStyleXfAt(int idx) { + return idx < styleXfs.size() ? styleXfs.get(idx) : null; + } + public int putCellStyleXf(CTXf cellStyleXf) { + styleXfs.add(cellStyleXf); + return styleXfs.size(); + } + public void replaceCellStyleXfAt(int idx, CTXf cellStyleXf) { + styleXfs.set(idx, cellStyleXf); + } + + /** + * get the size of cell styles + */ + public int getNumCellStyles(){ // Each cell style has a unique xfs entry // Several might share the same styleXfs entry return xfs.size(); - } + } - /** - * For unit testing only - */ - public int _getNumberFormatSize() { - return numberFormats.size(); - } + /** + * For unit testing only + */ + public int _getNumberFormatSize() { + return numberFormats.size(); + } - /** - * For unit testing only - */ - public int _getXfsSize() { - return xfs.size(); - } - /** - * For unit testing only - */ - public int _getStyleXfsSize() { - return styleXfs.size(); - } - /** - * For unit testing only! - */ - public CTStylesheet getCTStylesheet() { - return doc.getStyleSheet(); - } + /** + * For unit testing only + */ + public int _getXfsSize() { + return xfs.size(); + } + /** + * For unit testing only + */ + public int _getStyleXfsSize() { + return styleXfs.size(); + } + /** + * For unit testing only! + */ + public CTStylesheet getCTStylesheet() { + return doc.getStyleSheet(); + } public int _getDXfsSize() { return dxfs.size(); } - /** - * Write this table out as XML. - * - * @param out The stream to write to. - * @throws IOException if an error occurs while writing. - */ - public void writeTo(OutputStream out) throws IOException { - XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); + /** + * Write this table out as XML. + * + * @param out The stream to write to. + * @throws IOException if an error occurs while writing. + */ + public void writeTo(OutputStream out) throws IOException { + XmlOptions options = new XmlOptions(DEFAULT_XML_OPTIONS); - // Work on the current one - // Need to do this, as we don't handle - // all the possible entries yet - CTStylesheet styleSheet = doc.getStyleSheet(); + // Work on the current one + // Need to do this, as we don't handle + // all the possible entries yet + CTStylesheet styleSheet = doc.getStyleSheet(); - // Formats - CTNumFmts formats = CTNumFmts.Factory.newInstance(); - formats.setCount(numberFormats.size()); - for (Entry fmt : numberFormats.entrySet()) { - CTNumFmt ctFmt = formats.addNewNumFmt(); - ctFmt.setNumFmtId(fmt.getKey()); - ctFmt.setFormatCode(fmt.getValue()); - } - styleSheet.setNumFmts(formats); + // Formats + CTNumFmts formats = CTNumFmts.Factory.newInstance(); + formats.setCount(numberFormats.size()); + for (int fmtId=0; fmtId 0) { - CTCellXfs ctXfs = styleSheet.getCellXfs(); - if (ctXfs == null) { - ctXfs = CTCellXfs.Factory.newInstance(); - } - ctXfs.setCount(xfs.size()); - ctXfs.setXfArray( - xfs.toArray(new CTXf[xfs.size()]) - ); - styleSheet.setCellXfs(ctXfs); - } + // Xfs + if(xfs.size() > 0) { + CTCellXfs ctXfs = styleSheet.getCellXfs(); + if (ctXfs == null) { + ctXfs = CTCellXfs.Factory.newInstance(); + } + ctXfs.setCount(xfs.size()); + ctXfs.setXfArray( + xfs.toArray(new CTXf[xfs.size()]) + ); + styleSheet.setCellXfs(ctXfs); + } - // Style xfs - if(styleXfs.size() > 0) { - CTCellStyleXfs ctSXfs = styleSheet.getCellStyleXfs(); - if (ctSXfs == null) { - ctSXfs = CTCellStyleXfs.Factory.newInstance(); - } - ctSXfs.setCount(styleXfs.size()); - ctSXfs.setXfArray( - styleXfs.toArray(new CTXf[styleXfs.size()]) - ); - styleSheet.setCellStyleXfs(ctSXfs); - } + // Style xfs + if(styleXfs.size() > 0) { + CTCellStyleXfs ctSXfs = styleSheet.getCellStyleXfs(); + if (ctSXfs == null) { + ctSXfs = CTCellStyleXfs.Factory.newInstance(); + } + ctSXfs.setCount(styleXfs.size()); + ctSXfs.setXfArray( + styleXfs.toArray(new CTXf[styleXfs.size()]) + ); + styleSheet.setCellStyleXfs(ctSXfs); + } - // Style dxfs - if(dxfs.size() > 0) { - CTDxfs ctDxfs = styleSheet.getDxfs(); - if (ctDxfs == null) { - ctDxfs = CTDxfs.Factory.newInstance(); - } - ctDxfs.setCount(dxfs.size()); - ctDxfs.setDxfArray(dxfs.toArray(new CTDxf[dxfs.size()]) - ); - styleSheet.setDxfs(ctDxfs); - } + // Style dxfs + if(dxfs.size() > 0) { + CTDxfs ctDxfs = styleSheet.getDxfs(); + if (ctDxfs == null) { + ctDxfs = CTDxfs.Factory.newInstance(); + } + ctDxfs.setCount(dxfs.size()); + ctDxfs.setDxfArray(dxfs.toArray(new CTDxf[dxfs.size()])); + styleSheet.setDxfs(ctDxfs); + } - // Save - doc.save(out, options); - } + // Save + doc.save(out, options); + } - @Override - protected void commit() throws IOException { - PackagePart part = getPackagePart(); - OutputStream out = part.getOutputStream(); - writeTo(out); - out.close(); - } + @Override + protected void commit() throws IOException { + PackagePart part = getPackagePart(); + OutputStream out = part.getOutputStream(); + writeTo(out); + out.close(); + } - private void initialize() { - //CTFont ctFont = createDefaultFont(); - XSSFFont xssfFont = createDefaultFont(); - fonts.add(xssfFont); + private void initialize() { + //CTFont ctFont = createDefaultFont(); + XSSFFont xssfFont = createDefaultFont(); + fonts.add(xssfFont); - CTFill[] ctFill = createDefaultFills(); - fills.add(new XSSFCellFill(ctFill[0])); - fills.add(new XSSFCellFill(ctFill[1])); + CTFill[] ctFill = createDefaultFills(); + fills.add(new XSSFCellFill(ctFill[0])); + fills.add(new XSSFCellFill(ctFill[1])); - CTBorder ctBorder = createDefaultBorder(); - borders.add(new XSSFCellBorder(ctBorder)); + CTBorder ctBorder = createDefaultBorder(); + borders.add(new XSSFCellBorder(ctBorder)); - CTXf styleXf = createDefaultXf(); - styleXfs.add(styleXf); - CTXf xf = createDefaultXf(); - xf.setXfId(0); - xfs.add(xf); - } + CTXf styleXf = createDefaultXf(); + styleXfs.add(styleXf); + CTXf xf = createDefaultXf(); + xf.setXfId(0); + xfs.add(xf); + } - private static CTXf createDefaultXf() { - CTXf ctXf = CTXf.Factory.newInstance(); - ctXf.setNumFmtId(0); - ctXf.setFontId(0); - ctXf.setFillId(0); - ctXf.setBorderId(0); - return ctXf; - } - private static CTBorder createDefaultBorder() { - CTBorder ctBorder = CTBorder.Factory.newInstance(); - ctBorder.addNewBottom(); - ctBorder.addNewTop(); - ctBorder.addNewLeft(); - ctBorder.addNewRight(); - ctBorder.addNewDiagonal(); - return ctBorder; - } + private static CTXf createDefaultXf() { + CTXf ctXf = CTXf.Factory.newInstance(); + ctXf.setNumFmtId(0); + ctXf.setFontId(0); + ctXf.setFillId(0); + ctXf.setBorderId(0); + return ctXf; + } + private static CTBorder createDefaultBorder() { + CTBorder ctBorder = CTBorder.Factory.newInstance(); + ctBorder.addNewBottom(); + ctBorder.addNewTop(); + ctBorder.addNewLeft(); + ctBorder.addNewRight(); + ctBorder.addNewDiagonal(); + return ctBorder; + } - private static CTFill[] createDefaultFills() { - CTFill[] ctFill = new CTFill[]{CTFill.Factory.newInstance(),CTFill.Factory.newInstance()}; - ctFill[0].addNewPatternFill().setPatternType(STPatternType.NONE); - ctFill[1].addNewPatternFill().setPatternType(STPatternType.DARK_GRAY); - return ctFill; - } + private static CTFill[] createDefaultFills() { + CTFill[] ctFill = new CTFill[]{CTFill.Factory.newInstance(),CTFill.Factory.newInstance()}; + ctFill[0].addNewPatternFill().setPatternType(STPatternType.NONE); + ctFill[1].addNewPatternFill().setPatternType(STPatternType.DARK_GRAY); + return ctFill; + } - private static XSSFFont createDefaultFont() { - CTFont ctFont = CTFont.Factory.newInstance(); - XSSFFont xssfFont=new XSSFFont(ctFont, 0); - xssfFont.setFontHeightInPoints(XSSFFont.DEFAULT_FONT_SIZE); - xssfFont.setColor(XSSFFont.DEFAULT_FONT_COLOR);//setTheme - xssfFont.setFontName(XSSFFont.DEFAULT_FONT_NAME); - xssfFont.setFamily(FontFamily.SWISS); - xssfFont.setScheme(FontScheme.MINOR); - return xssfFont; - } + private static XSSFFont createDefaultFont() { + CTFont ctFont = CTFont.Factory.newInstance(); + XSSFFont xssfFont=new XSSFFont(ctFont, 0); + xssfFont.setFontHeightInPoints(XSSFFont.DEFAULT_FONT_SIZE); + xssfFont.setColor(XSSFFont.DEFAULT_FONT_COLOR);//setTheme + xssfFont.setFontName(XSSFFont.DEFAULT_FONT_NAME); + xssfFont.setFamily(FontFamily.SWISS); + xssfFont.setScheme(FontScheme.MINOR); + return xssfFont; + } - public CTDxf getDxfAt(int idx) { - return dxfs.get(idx); - } + public CTDxf getDxfAt(int idx) { + return dxfs.get(idx); + } - public int putDxf(CTDxf dxf) { - this.dxfs.add(dxf); - return this.dxfs.size(); - } + public int putDxf(CTDxf dxf) { + this.dxfs.add(dxf); + return this.dxfs.size(); + } - public XSSFCellStyle createCellStyle() { - CTXf xf = CTXf.Factory.newInstance(); - xf.setNumFmtId(0); - xf.setFontId(0); - xf.setFillId(0); - xf.setBorderId(0); - xf.setXfId(0); - int xfSize = styleXfs.size(); - int indexXf = putCellXf(xf); - return new XSSFCellStyle(indexXf - 1, xfSize - 1, this, theme); - } + public XSSFCellStyle createCellStyle() { + int xfSize = styleXfs.size(); + if (xfSize > MAXIMUM_STYLE_ID) + throw new IllegalStateException("The maximum number of Cell Styles was exceeded. " + + "You can define up to " + MAXIMUM_STYLE_ID + " style in a .xlsx Workbook"); - /** - * Finds a font that matches the one with the supplied attributes - */ - public XSSFFont findFont(short boldWeight, short color, short fontHeight, String name, boolean italic, boolean strikeout, short typeOffset, byte underline) { - for (XSSFFont font : fonts) { - if ( (font.getBoldweight() == boldWeight) - && font.getColor() == color - && font.getFontHeight() == fontHeight - && font.getFontName().equals(name) - && font.getItalic() == italic - && font.getStrikeout() == strikeout - && font.getTypeOffset() == typeOffset - && font.getUnderline() == underline) - { - return font; - } - } - return null; - } + CTXf xf = CTXf.Factory.newInstance(); + xf.setNumFmtId(0); + xf.setFontId(0); + xf.setFillId(0); + xf.setBorderId(0); + xf.setXfId(0); + int indexXf = putCellXf(xf); + return new XSSFCellStyle(indexXf - 1, xfSize - 1, this, theme); + } + + /** + * Finds a font that matches the one with the supplied attributes + */ + public XSSFFont findFont(short boldWeight, short color, short fontHeight, String name, boolean italic, boolean strikeout, short typeOffset, byte underline) { + for (XSSFFont font : fonts) { + if ( (font.getBoldweight() == boldWeight) + && font.getColor() == color + && font.getFontHeight() == fontHeight + && font.getFontName().equals(name) + && font.getItalic() == italic + && font.getStrikeout() == strikeout + && font.getTypeOffset() == typeOffset + && font.getUnderline() == underline) + { + return font; + } + } + return null; + } } diff --git a/src/ooxml/java/org/apache/poi/xssf/model/ThemesTable.java b/src/ooxml/java/org/apache/poi/xssf/model/ThemesTable.java index 0e8f90633..bf58989cc 100644 --- a/src/ooxml/java/org/apache/poi/xssf/model/ThemesTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/model/ThemesTable.java @@ -45,7 +45,7 @@ public class ThemesTable extends POIXMLDocumentPart { try { theme = ThemeDocument.Factory.parse(part.getInputStream()); } catch(XmlException e) { - throw new IOException(e.getLocalizedMessage()); + throw new IOException(e.getLocalizedMessage(), e); } } diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java index f590cc01a..b0d35803b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java @@ -22,6 +22,7 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.formula.FormulaParseException; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.usermodel.Cell; @@ -227,6 +228,11 @@ public class SXSSFCell implements Cell public void setCellValue(RichTextString value) { ensureRichTextStringType(); + + if(value.length() > SpreadsheetVersion.EXCEL2007.getMaxTextLength()){ + throw new IllegalArgumentException("The maximum length of cell contents (text) is 32,767 characters"); + } + ((RichTextValue)_value).setValue(value); } @@ -241,6 +247,11 @@ public class SXSSFCell implements Cell public void setCellValue(String value) { ensureTypeOrFormulaType(CELL_TYPE_STRING); + + if(value != null && value.length() > SpreadsheetVersion.EXCEL2007.getMaxTextLength()){ + throw new IllegalArgumentException("The maximum length of cell contents (text) is 32,767 characters"); + } + if(_value.getType()==CELL_TYPE_FORMULA) ((StringFormulaValue)_value).setPreEvaluatedValue(value); else diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java index ae6c4c4f8..cefc4f309 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFSheet.java @@ -431,7 +431,9 @@ public class SXSSFSheet implements Sheet, Cloneable } /** - * Returns the merged region at the specified index + * Returns the merged region at the specified index. If you want multiple + * regions, it is faster to call {@link #getMergedRegions()} than to call + * this each time. * * @return the merged region at the specified index */ @@ -440,6 +442,17 @@ public class SXSSFSheet implements Sheet, Cloneable return _sh.getMergedRegion(index); } + /** + * Returns the list of merged regions. If you want multiple regions, this is + * faster than calling {@link #getMergedRegion(int)} each time. + * + * @return the list of merged regions + */ + @Override + public List getMergedRegions() { + return _sh.getMergedRegions(); + } + /** * Returns an iterator of the physical rows * diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java index 87d8847bd..bd75179de 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java @@ -32,6 +32,7 @@ import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.internal.ZipHelper; import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CreationHelper; @@ -334,7 +335,7 @@ public class SXSSFWorkbook implements Workbook } private void injectData(File zipfile, OutputStream out) throws IOException { - ZipFile zip = new ZipFile(zipfile); + ZipFile zip = ZipHelper.openZipFile(zipfile); try { ZipOutputStream zos = new ZipOutputStream(out); @@ -709,9 +710,16 @@ public class SXSSFWorkbook implements Workbook @Override public void removeSheetAt(int index) { - XSSFSheet xSheet=_wb.getSheetAt(index); + // Get the sheet to be removed + XSSFSheet xSheet = _wb.getSheetAt(index); + SXSSFSheet sxSheet = getSXSSFSheet(xSheet); + + // De-register it _wb.removeSheetAt(index); deregisterSheetMapping(xSheet); + + // Clean up temporary resources + sxSheet.dispose(); } /** @@ -831,7 +839,7 @@ public class SXSSFWorkbook implements Workbook /** * Closes the underlying {@link XSSFWorkbook} and {@link OPCPackage} - * on which this Workbook is based, if any. Has no effect on Worbooks + * on which this Workbook is based, if any. Has no effect on Workbooks * created from scratch. */ @Override diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java index d91f5ca81..e307a4a30 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBorderFormatting.java @@ -17,149 +17,230 @@ package org.apache.poi.xssf.usermodel; import org.apache.poi.ss.usermodel.BorderFormatting; +import org.apache.poi.ss.usermodel.Color; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; /** - * @author Yegor Kozlov + * XSSF high level representation for Border Formatting component + * of Conditional Formatting settings */ public class XSSFBorderFormatting implements BorderFormatting { CTBorder _border; - /*package*/ XSSFBorderFormatting(CTBorder border){ + /*package*/ XSSFBorderFormatting(CTBorder border) { _border = border; } - public short getBorderBottom(){ + public short getBorderBottom() { STBorderStyle.Enum ptrn = _border.isSetBottom() ? _border.getBottom().getStyle() : null; return ptrn == null ? BORDER_NONE : (short)(ptrn.intValue() - 1); } - public short getBorderDiagonal(){ + public short getBorderDiagonal() { STBorderStyle.Enum ptrn = _border.isSetDiagonal() ? _border.getDiagonal().getStyle() : null; return ptrn == null ? BORDER_NONE : (short)(ptrn.intValue() - 1); } - public short getBorderLeft(){ + public short getBorderLeft() { STBorderStyle.Enum ptrn = _border.isSetLeft() ? _border.getLeft().getStyle() : null; return ptrn == null ? BORDER_NONE : (short)(ptrn.intValue() - 1); } - public short getBorderRight(){ + public short getBorderRight() { STBorderStyle.Enum ptrn = _border.isSetRight() ? _border.getRight().getStyle() : null; return ptrn == null ? BORDER_NONE : (short)(ptrn.intValue() - 1); } - public short getBorderTop(){ + public short getBorderTop() { STBorderStyle.Enum ptrn = _border.isSetTop() ? _border.getTop().getStyle() : null; return ptrn == null ? BORDER_NONE : (short)(ptrn.intValue() - 1); } - public short getBottomBorderColor(){ - if(!_border.isSetBottom()) return 0; + public XSSFColor getBottomBorderColorColor() { + if(!_border.isSetBottom()) return null; CTBorderPr pr = _border.getBottom(); - return (short)pr.getColor().getIndexed(); + return new XSSFColor(pr.getColor()); + } + public short getBottomBorderColor() { + XSSFColor color = getBottomBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); } - public short getDiagonalBorderColor(){ - if(!_border.isSetDiagonal()) return 0; + public XSSFColor getDiagonalBorderColorColor() { + if(!_border.isSetDiagonal()) return null; CTBorderPr pr = _border.getDiagonal(); - return (short)pr.getColor().getIndexed(); + return new XSSFColor(pr.getColor()); + } + public short getDiagonalBorderColor() { + XSSFColor color = getDiagonalBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); } - public short getLeftBorderColor(){ - if(!_border.isSetLeft()) return 0; + public XSSFColor getLeftBorderColorColor() { + if(!_border.isSetLeft()) return null; CTBorderPr pr = _border.getLeft(); - return (short)pr.getColor().getIndexed(); + return new XSSFColor(pr.getColor()); + } + public short getLeftBorderColor() { + XSSFColor color = getLeftBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); } - public short getRightBorderColor(){ - if(!_border.isSetRight()) return 0; + public XSSFColor getRightBorderColorColor() { + if(!_border.isSetRight()) return null; CTBorderPr pr = _border.getRight(); - return (short)pr.getColor().getIndexed(); + return new XSSFColor(pr.getColor()); + } + public short getRightBorderColor() { + XSSFColor color = getRightBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); } - public short getTopBorderColor(){ - if(!_border.isSetTop()) return 0; + public XSSFColor getTopBorderColorColor() { + if(!_border.isSetTop()) return null; CTBorderPr pr = _border.getTop(); - return (short)pr.getColor().getIndexed(); + return new XSSFColor(pr.getColor()); + } + public short getTopBorderColor() { + XSSFColor color = getRightBorderColorColor(); + if (color == null) return 0; + return color.getIndexed(); } - public void setBorderBottom(short border){ + public void setBorderBottom(short border) { CTBorderPr pr = _border.isSetBottom() ? _border.getBottom() : _border.addNewBottom(); if(border == BORDER_NONE) _border.unsetBottom(); else pr.setStyle(STBorderStyle.Enum.forInt(border + 1)); } - public void setBorderDiagonal(short border){ + public void setBorderDiagonal(short border) { CTBorderPr pr = _border.isSetDiagonal() ? _border.getDiagonal() : _border.addNewDiagonal(); if(border == BORDER_NONE) _border.unsetDiagonal(); else pr.setStyle(STBorderStyle.Enum.forInt(border + 1)); } - public void setBorderLeft(short border){ + public void setBorderLeft(short border) { CTBorderPr pr = _border.isSetLeft() ? _border.getLeft() : _border.addNewLeft(); if(border == BORDER_NONE) _border.unsetLeft(); else pr.setStyle(STBorderStyle.Enum.forInt(border + 1)); } - public void setBorderRight(short border){ + public void setBorderRight(short border) { CTBorderPr pr = _border.isSetRight() ? _border.getRight() : _border.addNewRight(); if(border == BORDER_NONE) _border.unsetRight(); else pr.setStyle(STBorderStyle.Enum.forInt(border + 1)); } - public void setBorderTop(short border){ + public void setBorderTop(short border) { CTBorderPr pr = _border.isSetTop() ? _border.getTop() : _border.addNewTop(); if(border == BORDER_NONE) _border.unsetTop(); else pr.setStyle(STBorderStyle.Enum.forInt(border + 1)); } - public void setBottomBorderColor(short color){ + public void setBottomBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setBottomBorderColor((CTColor)null); + else setBottomBorderColor(xcolor.getCTColor()); + } + public void setBottomBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setBottomBorderColor(ctColor); + } + public void setBottomBorderColor(CTColor color) { CTBorderPr pr = _border.isSetBottom() ? _border.getBottom() : _border.addNewBottom(); - - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - pr.setColor(ctColor); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } } - public void setDiagonalBorderColor(short color){ + public void setDiagonalBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setDiagonalBorderColor((CTColor)null); + else setDiagonalBorderColor(xcolor.getCTColor()); + } + public void setDiagonalBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setDiagonalBorderColor(ctColor); + } + public void setDiagonalBorderColor(CTColor color) { CTBorderPr pr = _border.isSetDiagonal() ? _border.getDiagonal() : _border.addNewDiagonal(); - - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - pr.setColor(ctColor); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } } - public void setLeftBorderColor(short color){ + public void setLeftBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setLeftBorderColor((CTColor)null); + else setLeftBorderColor(xcolor.getCTColor()); + } + public void setLeftBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setLeftBorderColor(ctColor); + } + public void setLeftBorderColor(CTColor color) { CTBorderPr pr = _border.isSetLeft() ? _border.getLeft() : _border.addNewLeft(); - - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - pr.setColor(ctColor); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } } - public void setRightBorderColor(short color){ + public void setRightBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setRightBorderColor((CTColor)null); + else setRightBorderColor(xcolor.getCTColor()); + } + public void setRightBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setRightBorderColor(ctColor); + } + public void setRightBorderColor(CTColor color) { CTBorderPr pr = _border.isSetRight() ? _border.getRight() : _border.addNewRight(); - - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - pr.setColor(ctColor); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } } - public void setTopBorderColor(short color){ + public void setTopBorderColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) setTopBorderColor((CTColor)null); + else setTopBorderColor(xcolor.getCTColor()); + } + public void setTopBorderColor(short color) { + CTColor ctColor = CTColor.Factory.newInstance(); + ctColor.setIndexed(color); + setTopBorderColor(ctColor); + } + public void setTopBorderColor(CTColor color) { CTBorderPr pr = _border.isSetTop() ? _border.getTop() : _border.addNewTop(); - - CTColor ctColor = CTColor.Factory.newInstance(); - ctColor.setIndexed(color); - pr.setColor(ctColor); + if (color == null) { + pr.unsetColor(); + } else { + pr.setColor(color); + } } - } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java index df8cbf2d2..5c16f05e8 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java @@ -346,6 +346,11 @@ public final class XSSFCell implements Cell { setCellType(Cell.CELL_TYPE_BLANK); return; } + + if(str.length() > SpreadsheetVersion.EXCEL2007.getMaxTextLength()){ + throw new IllegalArgumentException("The maximum length of cell contents (text) is 32,767 characters"); + } + int cellType = getCellType(); switch(cellType){ case Cell.CELL_TYPE_FORMULA: diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java index d1f075907..f83facdda 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCellStyle.java @@ -154,6 +154,13 @@ public class XSSFCellStyle implements CellStyle { _cellXf = CTXf.Factory.parse( src.getCoreXf().toString() ); + + // bug 56295: ensure that the fills is available and set correctly + CTFill fill = CTFill.Factory.parse( + src.getCTFill().toString() + ); + addFill(fill); + // Swap it over _stylesSource.replaceCellXfAt(_cellXfId, _cellXf); } catch(XmlException e) { @@ -187,6 +194,13 @@ public class XSSFCellStyle implements CellStyle { } } + private void addFill(CTFill fill) { + int idx = _stylesSource.putFill(new XSSFCellFill(fill)); + + _cellXf.setFillId(idx); + _cellXf.setApplyFill(true); + } + /** * Get the type of horizontal alignment for the cell * @@ -444,7 +458,8 @@ public class XSSFCellStyle implements CellStyle { * @return XSSFColor - fill color or null if not set */ public XSSFColor getFillBackgroundXSSFColor() { - if(!_cellXf.getApplyFill()) return null; + // bug 56295: handle missing applyFill attribute as "true" because Excel does as well + if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return null; int fillIndex = (int)_cellXf.getFillId(); XSSFCellFill fg = _stylesSource.getFillAt(fillIndex); @@ -480,7 +495,8 @@ public class XSSFCellStyle implements CellStyle { * @return XSSFColor - fill color or null if not set */ public XSSFColor getFillForegroundXSSFColor() { - if(!_cellXf.getApplyFill()) return null; + // bug 56295: handle missing applyFill attribute as "true" because Excel does as well + if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return null; int fillIndex = (int)_cellXf.getFillId(); XSSFCellFill fg = _stylesSource.getFillAt(fillIndex); @@ -515,7 +531,8 @@ public class XSSFCellStyle implements CellStyle { * @see org.apache.poi.ss.usermodel.CellStyle#DIAMONDS */ public short getFillPattern() { - if(!_cellXf.getApplyFill()) return 0; + // bug 56295: handle missing applyFill attribute as "true" because Excel does as well + if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return 0; int fillIndex = (int)_cellXf.getFillId(); XSSFCellFill fill = _stylesSource.getFillAt(fillIndex); @@ -586,6 +603,9 @@ public class XSSFCellStyle implements CellStyle { public short getIndex() { return (short)this._cellXfId; } + protected int getUIndex() { + return this._cellXfId; + } /** * Get the color to use for the left border @@ -957,6 +977,15 @@ public class XSSFCellStyle implements CellStyle { * @param fmt the index of a data format */ public void setDataFormat(short fmt) { + // XSSF supports >32,767 formats + setDataFormat(fmt&0xffff); + } + /** + * Set the index of a data format + * + * @param fmt the index of a data format + */ + public void setDataFormat(int fmt) { _cellXf.setApplyNumberFormat(true); _cellXf.setNumFmtId(fmt); } @@ -996,10 +1025,7 @@ public class XSSFCellStyle implements CellStyle { ptrn.setBgColor(color.getCTColor()); } - int idx = _stylesSource.putFill(new XSSFCellFill(ct)); - - _cellXf.setFillId(idx); - _cellXf.setApplyFill(true); + addFill(ct); } /** @@ -1052,10 +1078,7 @@ public class XSSFCellStyle implements CellStyle { ptrn.setFgColor(color.getCTColor()); } - int idx = _stylesSource.putFill(new XSSFCellFill(ct)); - - _cellXf.setFillId(idx); - _cellXf.setApplyFill(true); + addFill(ct); } /** @@ -1076,7 +1099,8 @@ public class XSSFCellStyle implements CellStyle { */ private CTFill getCTFill(){ CTFill ct; - if(_cellXf.getApplyFill()) { + // bug 56295: handle missing applyFill attribute as "true" because Excel does as well + if(!_cellXf.isSetApplyFill() || _cellXf.getApplyFill()) { int fillIndex = (int)_cellXf.getFillId(); XSSFCellFill cf = _stylesSource.getFillAt(fillIndex); @@ -1135,10 +1159,7 @@ public class XSSFCellStyle implements CellStyle { if(fp == NO_FILL && ptrn.isSetPatternType()) ptrn.unsetPatternType(); else ptrn.setPatternType(STPatternType.Enum.forInt(fp + 1)); - int idx = _stylesSource.putFill(new XSSFCellFill(ct)); - - _cellXf.setFillId(idx); - _cellXf.setApplyFill(true); + addFill(ct); } /** diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColor.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColor.java index 3082e5387..19fd5a5b4 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColor.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFColor.java @@ -170,10 +170,7 @@ public class XSSFColor implements Color { return null; } for(byte c : rgb) { - int i = (int)c; - if(i < 0) { - i += 256; - } + int i = c & 0xff; String cs = Integer.toHexString(i); if(cs.length() == 1) { sb.append('0'); @@ -316,6 +313,13 @@ public class XSSFColor implements Color { return ctColor; } + public static XSSFColor toXSSFColor(Color color) { + if (color != null && !(color instanceof XSSFColor)) { + throw new IllegalArgumentException("Only XSSFColor objects are supported"); + } + return (XSSFColor)color; + } + public int hashCode(){ return ctColor.toString().hashCode(); } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java index 5fdd3aa2c..51ef179e6 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFComment.java @@ -145,9 +145,17 @@ public class XSSFComment implements Comment { _comment.setRef(newRef); _comments.referenceUpdated(oldRef, _comment); - if(_vmlShape != null) _vmlShape.getClientDataArray(0).setRowArray(0, new BigInteger(String.valueOf(row))); + if(_vmlShape != null) { + _vmlShape.getClientDataArray(0).setRowArray(0, + new BigInteger(String.valueOf(row))); + + // There is a very odd xmlbeans bug when changing the row + // arrays which can lead to corrupt pointer + // This call seems to fix them again... See bug #50795 + _vmlShape.getClientDataList().toString(); + } } - + /** * @return the rich text string of the comment */ diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormatting.java index 127c03783..53eb41b12 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormatting.java @@ -98,4 +98,8 @@ public class XSSFConditionalFormatting implements ConditionalFormatting { public int getNumberOfRules(){ return _cf.sizeOfCfRuleArray(); } + + public String toString() { + return _cf.toString(); + } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java index 64e49f947..814e73ca0 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingRule.java @@ -19,23 +19,48 @@ package org.apache.poi.xssf.usermodel; +import java.util.HashMap; +import java.util.Map; + import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.xssf.usermodel.XSSFFontFormatting; import org.apache.poi.xssf.model.StylesTable; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfType; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.STConditionalFormattingOperator; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxf; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; /** - * @author Yegor Kozlov + * XSSF suport for Conditional Formatting rules */ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule { private final CTCfRule _cfRule; private XSSFSheet _sh; + + private static Map typeLookup = new HashMap(); + static { + typeLookup.put(STCfType.CELL_IS, ConditionType.CELL_VALUE_IS); + typeLookup.put(STCfType.EXPRESSION, ConditionType.FORMULA); + typeLookup.put(STCfType.COLOR_SCALE, ConditionType.COLOR_SCALE); + typeLookup.put(STCfType.DATA_BAR, ConditionType.DATA_BAR); + typeLookup.put(STCfType.ICON_SET, ConditionType.ICON_SET); + + // These are all subtypes of Filter, we think... + typeLookup.put(STCfType.TOP_10, ConditionType.FILTER); + typeLookup.put(STCfType.UNIQUE_VALUES, ConditionType.FILTER); + typeLookup.put(STCfType.DUPLICATE_VALUES, ConditionType.FILTER); + typeLookup.put(STCfType.CONTAINS_TEXT, ConditionType.FILTER); + typeLookup.put(STCfType.NOT_CONTAINS_TEXT, ConditionType.FILTER); + typeLookup.put(STCfType.BEGINS_WITH, ConditionType.FILTER); + typeLookup.put(STCfType.ENDS_WITH, ConditionType.FILTER); + typeLookup.put(STCfType.CONTAINS_BLANKS, ConditionType.FILTER); + typeLookup.put(STCfType.NOT_CONTAINS_BLANKS, ConditionType.FILTER); + typeLookup.put(STCfType.CONTAINS_ERRORS, ConditionType.FILTER); + typeLookup.put(STCfType.NOT_CONTAINS_ERRORS, ConditionType.FILTER); + typeLookup.put(STCfType.TIME_PERIOD, ConditionType.FILTER); + typeLookup.put(STCfType.ABOVE_AVERAGE, ConditionType.FILTER); + } + + // TODO Support types beyond CELL_VALUE_IS and FORMULA /*package*/ XSSFConditionalFormattingRule(XSSFSheet sh){ _cfRule = CTCfRule.Factory.newInstance(); @@ -149,23 +174,69 @@ public class XSSFConditionalFormattingRule implements ConditionalFormattingRule return new XSSFPatternFormatting(dxf.getFill()); } + + public XSSFIconMultiStateFormatting createMultiStateFormatting(IconSet iconSet) { + // Is it already there? + if (_cfRule.isSetIconSet() && _cfRule.getType() == STCfType.ICON_SET) + return getMultiStateFormatting(); + + // Mark it as being an Icon Set + _cfRule.setType(STCfType.ICON_SET); + + // Ensure the right element + CTIconSet icons = null; + if (_cfRule.isSetIconSet()) { + icons = _cfRule.getIconSet(); + } else { + icons = _cfRule.addNewIconSet(); + } + // Set the type of the icon set + if (iconSet.name != null) { + STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(iconSet.name); + icons.setIconSet(xIconSet); + } + + // Add a default set of thresholds + int jump = 100 / iconSet.num; + STCfvoType.Enum type = STCfvoType.Enum.forString(RangeType.PERCENT.name); + for (int i=0; i - * MUST be either {@link ConditionalFormattingRule#CONDITION_TYPE_CELL_VALUE_IS} - * or {@link ConditionalFormattingRule#CONDITION_TYPE_FORMULA} + * MUST be one of the IDs of a {@link ConditionType} *

    * * @return the type of condition */ public byte getConditionType(){ - switch (_cfRule.getType().intValue()){ - case STCfType.INT_EXPRESSION: return ConditionalFormattingRule.CONDITION_TYPE_FORMULA; - case STCfType.INT_CELL_IS: return ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS; - } + ConditionType type = getConditionTypeType(); + if (type != null) return type.id; return 0; } + + /** + * Type of conditional formatting rule. + */ + public ConditionType getConditionTypeType() { + return typeLookup.get(_cfRule.getType()); + } /** * The comparison function used when the type of conditional formatting is set to diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java new file mode 100644 index 000000000..bfdd87807 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFConditionalFormattingThreshold.java @@ -0,0 +1,77 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ + +package org.apache.poi.xssf.usermodel; + +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfvoType; + +/** + * High level representation for Icon / Multi-State / Databar / + * Colour Scale change thresholds + */ +public class XSSFConditionalFormattingThreshold implements org.apache.poi.ss.usermodel.ConditionalFormattingThreshold { + private CTCfvo cfvo; + + protected XSSFConditionalFormattingThreshold(CTCfvo cfvo) { + this.cfvo = cfvo; + } + + protected CTCfvo getCTCfvo() { + return cfvo; + } + + public RangeType getRangeType() { + return RangeType.byName(cfvo.getType().toString()); + } + public void setRangeType(RangeType type) { + STCfvoType.Enum xtype = STCfvoType.Enum.forString(type.name); + cfvo.setType(xtype); + } + + public String getFormula() { + if (cfvo.getType() == STCfvoType.FORMULA) { + return cfvo.getVal(); + } + return null; + } + public void setFormula(String formula) { + cfvo.setVal(formula); + } + + public Double getValue() { + if (cfvo.getType() == STCfvoType.FORMULA || + cfvo.getType() == STCfvoType.MIN || + cfvo.getType() == STCfvoType.MAX) { + return null; + } + if (cfvo.isSetVal()) { + return Double.parseDouble(cfvo.getVal()); + } else { + return null; + } + } + public void setValue(Double value) { + if (value == null) { + cfvo.unsetVal(); + } else { + cfvo.setVal(value.toString()); + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataFormat.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataFormat.java index 00ac90736..870c6c025 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataFormat.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataFormat.java @@ -51,6 +51,14 @@ public class XSSFDataFormat implements DataFormat { * @return string represented at index of format or null if there is not a format at that index */ public String getFormat(short index) { + return getFormat(index&0xffff); + } + /** + * get the format string that matches the given format index + * @param index of a format + * @return string represented at index of format or null if there is not a format at that index + */ + public String getFormat(int index) { String fmt = stylesSource.getNumberFormatAt(index); if(fmt == null) fmt = BuiltinFormats.getBuiltinFormat(index); return fmt; diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java index a5d8bdd40..e788cf893 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFontFormatting.java @@ -80,7 +80,6 @@ public class XSSFFontFormatting implements FontFormatting { return (short)idx; } - /** * @param color font color index */ @@ -91,16 +90,28 @@ public class XSSFFontFormatting implements FontFormatting { } } - /** - * - * @return xssf color wrapper or null if color info is missing - */ - public XSSFColor getXSSFColor(){ + public XSSFColor getFontColor() { if(_font.sizeOfColorArray() == 0) return null; return new XSSFColor(_font.getColorArray(0)); } + public void setFontColor(Color color) { + XSSFColor xcolor = XSSFColor.toXSSFColor(color); + if (xcolor == null) { + _font.getColorList().clear(); + } else { + _font.setColorArray(0, xcolor.getCTColor()); + } + } + + /** + * @deprecated use {@link #getFontColor()} + */ + public XSSFColor getXSSFColor(){ + return getFontColor(); + } + /** * gets the height of the font in 1/20th point units * diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java new file mode 100644 index 000000000..81883bb06 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFIconMultiStateFormatting.java @@ -0,0 +1,85 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfvo; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIconSet; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STIconSetType; + +/** + * High level representation for Icon / Multi-State Formatting + * component of Conditional Formatting settings + */ +public class XSSFIconMultiStateFormatting implements IconMultiStateFormatting { + CTIconSet _iconset; + + /*package*/ XSSFIconMultiStateFormatting(CTIconSet iconset){ + _iconset = iconset; + } + + public IconSet getIconSet() { + String set = _iconset.getIconSet().toString(); + return IconSet.byName(set); + } + public void setIconSet(IconSet set) { + STIconSetType.Enum xIconSet = STIconSetType.Enum.forString(set.name); + _iconset.setIconSet(xIconSet); + } + + public boolean isIconOnly() { + if (_iconset.isSetShowValue()) + return !_iconset.getShowValue(); + return false; + } + public void setIconOnly(boolean only) { + _iconset.setShowValue(!only); + } + + public boolean isReversed() { + if (_iconset.isSetReverse()) + return _iconset.getReverse(); + return false; + } + public void setReversed(boolean reversed) { + _iconset.setReverse(reversed); + } + + @SuppressWarnings("deprecation") + public XSSFConditionalFormattingThreshold[] getThresholds() { + CTCfvo[] cfvos = _iconset.getCfvoArray(); + XSSFConditionalFormattingThreshold[] t = + new XSSFConditionalFormattingThreshold[cfvos.length]; + for (int i=0; i _rows; + private SortedMap _rows; private List hyperlinks; private ColumnHelper columnHelper; private CommentsTable sheetComments; @@ -140,7 +142,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { * Master shared formula is the first formula in a group of shared formulas is saved in the f element. */ private Map sharedFormulas; - private TreeMap tables; + private SortedMap tables; private List arrayFormulas; private XSSFDataValidationHelper dataValidationHelper; @@ -600,6 +602,15 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { CTRow ctRow; XSSFRow prev = _rows.get(rownum); if(prev != null){ + // the Cells in an existing row are invalidated on-purpose, in order to clean up correctly, we + // need to call the remove, so things like ArrayFormulas and CalculationChain updates are done + // correctly. + // We remove the cell this way as the internal cell-list is changed by the remove call and + // thus would cause ConcurrentModificationException otherwise + while(prev.getFirstCellNum() != -1) { + prev.removeCell(prev.getCell(prev.getFirstCellNum())); + } + ctRow = prev.getCTRow(); ctRow.set(CTRow.Factory.newInstance()); } else { @@ -1071,6 +1082,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } /** + * Returns the merged region at the specified index. If you want multiple + * regions, it is faster to call {@link #getMergedRegions()} than to call + * this each time. + * * @return the merged region at the specified index * @throws IllegalStateException if this worksheet does not contain merged regions */ @@ -1084,6 +1099,27 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { return CellRangeAddress.valueOf(ref); } + /** + * Returns the list of merged regions. If you want multiple regions, this is + * faster than calling {@link #getMergedRegion(int)} each time. + * + * @return the list of merged regions + * @throws IllegalStateException if this worksheet does not contain merged regions + */ + @SuppressWarnings("deprecation") + @Override + public List getMergedRegions() { + CTMergeCells ctMergeCells = worksheet.getMergeCells(); + if(ctMergeCells == null) throw new IllegalStateException("This worksheet does not contain merged regions"); + + List addresses = new ArrayList(); + for(CTMergeCell ctMergeCell : ctMergeCells.getMergeCellArray()) { + String ref = ctMergeCell.getRef(); + addresses.add(CellRangeAddress.valueOf(ref)); + } + return addresses; + } + /** * Returns the number of merged regions defined in this worksheet * @@ -2555,38 +2591,90 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { */ @Override @SuppressWarnings("deprecation") //YK: getXYZArray() array accessors are deprecated in xmlbeans with JDK 1.5 support - public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) { - // first remove all rows which will be overwritten + public void shiftRows(int startRow, int endRow, final int n, boolean copyRowHeight, boolean resetOriginalRowHeight) { + XSSFVMLDrawing vml = getVMLDrawing(false); + + // first remove all rows which will be overwritten for (Iterator it = rowIterator() ; it.hasNext() ; ) { XSSFRow row = (XSSFRow)it.next(); int rownum = row.getRowNum(); // check if we should remove this row as it will be overwritten by the data later - if (removeRow(startRow, endRow, n, rownum)) { + if (shouldRemoveRow(startRow, endRow, n, rownum)) { // remove row from worksheet.getSheetData row array int idx = _rows.headMap(row.getRowNum()).size(); worksheet.getSheetData().removeRow(idx); + // remove row from _rows it.remove(); + + // also remove any comments associated with this row + if(sheetComments != null){ + CTCommentList lst = sheetComments.getCTComments().getCommentList(); + for (CTComment comment : lst.getCommentArray()) { + String strRef = comment.getRef(); + CellReference ref = new CellReference(strRef); + + // is this comment part of the current row? + if(ref.getRow() == rownum) { + sheetComments.removeComment(strRef); + vml.removeCommentShape(ref.getRow(), ref.getCol()); + } + } + } } } // then do the actual moving and also adjust comments/rowHeight + // we need to sort it in a way so the shifting does not mess up the structures, + // i.e. when shifting down, start from down and go up, when shifting up, vice-versa + SortedMap commentsToShift = new TreeMap(new Comparator() { + public int compare(XSSFComment o1, XSSFComment o2) { + int row1 = o1.getRow(); + int row2 = o2.getRow(); + + if(row1 == row2) { + // ordering is not important when row is equal, but don't return zero to still + // get multiple comments per row into the map + return o1.hashCode() - o2.hashCode(); + } + + // when shifting down, sort higher row-values first + if(n > 0) { + return row1 < row2 ? 1 : -1; + } else { + // sort lower-row values first when shifting up + return row1 > row2 ? 1 : -1; + } + } + }); + + for (Iterator it = rowIterator() ; it.hasNext() ; ) { XSSFRow row = (XSSFRow)it.next(); int rownum = row.getRowNum(); if(sheetComments != null){ - //TODO shift Note's anchor in the associated /xl/drawing/vmlDrawings#.vml - CTCommentList lst = sheetComments.getCTComments().getCommentList(); - for (CTComment comment : lst.getCommentArray()) { - String oldRef = comment.getRef(); - CellReference ref = new CellReference(oldRef); - if(ref.getRow() == rownum){ - ref = new CellReference(rownum + n, ref.getCol()); - comment.setRef(ref.formatAsString()); - sheetComments.referenceUpdated(oldRef, comment); - } + // calculate the new rownum + int newrownum = shiftedRowNum(startRow, endRow, n, rownum); + + // is there a change necessary for the current row? + if(newrownum != rownum) { + CTCommentList lst = sheetComments.getCTComments().getCommentList(); + for (CTComment comment : lst.getCommentArray()) { + String oldRef = comment.getRef(); + CellReference ref = new CellReference(oldRef); + + // is this comment part of the current row? + if(ref.getRow() == rownum) { + XSSFComment xssfComment = new XSSFComment(sheetComments, comment, + vml == null ? null : vml.findCommentShape(rownum, ref.getCol())); + + // we should not perform the shifting right here as we would then find + // already shifted comments and would shift them again... + commentsToShift.put(xssfComment, newrownum); + } + } } } @@ -2598,6 +2686,14 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { row.shift(n); } + + // adjust all the affected comment-structures now + // the Map is sorted and thus provides them in the order that we need here, + // i.e. from down to up if shifting down, vice-versa otherwise + for(Map.Entry entry : commentsToShift.entrySet()) { + entry.getKey().setRow(entry.getValue()); + } + XSSFRowShifter rowShifter = new XSSFRowShifter(this); int sheetIndex = getWorkbook().getSheetIndex(this); @@ -2611,13 +2707,40 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { rowShifter.updateConditionalFormatting(shifter); //rebuild the _rows map - TreeMap map = new TreeMap(); + SortedMap map = new TreeMap(); for(XSSFRow r : _rows.values()) { map.put(r.getRowNum(), r); } _rows = map; } + private int shiftedRowNum(int startRow, int endRow, int n, int rownum) { + // no change if before any affected row + if(rownum < startRow && (n > 0 || (startRow - rownum) > n)) { + return rownum; + } + + // no change if after any affected row + if(rownum > endRow && (n < 0 || (rownum - endRow) > n)) { + return rownum; + } + + // row before and things are moved up + if(rownum < startRow) { + // row is moved down by the shifting + return rownum + (endRow - startRow); + } + + // row is after and things are moved down + if(rownum > endRow) { + // row is moved up by the shifting + return rownum - (endRow - startRow); + } + + // row is part of the shifted block + return rownum + n; + } + /** * Location of the top left visible cell Location of the top left visible cell in the bottom right * pane (when in Left-to-Right mode). @@ -2873,7 +2996,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { return sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr(); } - private boolean removeRow(int startRow, int endRow, int n, int rownum) { + private boolean shouldRemoveRow(int startRow, int endRow, int n, int rownum) { // is this row in the target-window where the moved rows will land? if (rownum >= (startRow + n) && rownum <= (endRow + n)) { // only remove it if the current row is not part of the data that is copied diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheetConditionalFormatting.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheetConditionalFormatting.java index 8c83f6f16..afd8885e1 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheetConditionalFormatting.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheetConditionalFormatting.java @@ -27,6 +27,7 @@ import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.ComparisonOperator; import org.apache.poi.ss.usermodel.ConditionalFormatting; import org.apache.poi.ss.usermodel.ConditionalFormattingRule; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.usermodel.SheetConditionalFormatting; import org.apache.poi.ss.util.CellRangeAddress; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule; @@ -36,9 +37,12 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCfType; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STConditionalFormattingOperator; /** - * @author Yegor Kozlov + * XSSF Conditional Formattings */ public class XSSFSheetConditionalFormatting implements SheetConditionalFormatting { + /** Office 2010 Conditional Formatting extensions namespace */ + protected static final String CF_EXT_2009_NS_X14 = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"; + private final XSSFSheet _sheet; /* package */ XSSFSheetConditionalFormatting(XSSFSheet sheet) { @@ -115,6 +119,27 @@ public class XSSFSheetConditionalFormatting implements SheetConditionalFormattin return rule; } + /** + * A factory method allowing the creation of conditional formatting + * rules using an Icon Set / Multi-State formatting. + * The thresholds for it will be created, but will be empty + * and require configuring with + * {@link XSSFConditionalFormattingRule#getMultiStateFormatting()} + * then + * {@link XSSFIconMultiStateFormatting#getThresholds()} + */ + public XSSFConditionalFormattingRule createConditionalFormattingRule(IconSet iconSet) { + XSSFConditionalFormattingRule rule = new XSSFConditionalFormattingRule(_sheet); + + // Have it setup, with suitable defaults + rule.createMultiStateFormatting(iconSet); + + // All done! + return rule; + } + + // TODO Support types beyond CELL_VALUE_IS and FORMULA and ICONs + @SuppressWarnings("deprecation") public int addConditionalFormatting(CellRangeAddress[] regions, ConditionalFormattingRule[] cfRules) { if (regions == null) { diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java index c89d0cdb3..6500c1603 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java @@ -709,13 +709,19 @@ public class XSSFTextParagraph implements Iterable{ public boolean isBullet() { ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getLevel()){ public boolean fetch(CTTextParagraphProperties props){ - if(props.isSetBuNone()) { + if (props.isSetBuNone()) { setValue(false); return true; } - if(props.isSetBuFont() || props.isSetBuChar() || props.isSetBuAutoNum()){ - setValue(true); - return true; + if (props.isSetBuFont()) { + if (props.isSetBuChar() || props.isSetBuAutoNum()) { + setValue(true); + return true; + } else { + // Excel treats text with buFont but no char/autonum + // as not bulleted + // Possibly the font is just used if bullets turned on again? + } } return false; } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVBAPart.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVBAPart.java new file mode 100644 index 000000000..263dae0dd --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVBAPart.java @@ -0,0 +1,52 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.POIXMLDocumentPart; +import org.apache.poi.openxml4j.opc.PackagePart; +import org.apache.poi.openxml4j.opc.PackageRelationship; + +public class XSSFVBAPart extends POIXMLDocumentPart { + + /** + * Create a new XSSFVBAPart node + */ + protected XSSFVBAPart() { + super(); + } + + /** + * Construct XSSFVBAPart from a package part + * + * @param part the package part holding the VBA data, + * @param rel the package relationship holding this part + */ + protected XSSFVBAPart(PackagePart part, PackageRelationship rel) { + super(part, rel); + } + + /** + * Like *PictureData, VBA objects store the actual content in the part + * directly without keeping a copy like all others therefore we need to + * handle them differently. + */ + protected void prepareForCommit() { + // do not clear the part here + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java index a1458662b..75f292fa6 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVMLDrawing.java @@ -68,6 +68,7 @@ public final class XSSFVMLDrawing extends POIXMLDocumentPart { private static final QName QNAME_SHAPE_LAYOUT = new QName("urn:schemas-microsoft-com:office:office", "shapelayout"); private static final QName QNAME_SHAPE_TYPE = new QName("urn:schemas-microsoft-com:vml", "shapetype"); private static final QName QNAME_SHAPE = new QName("urn:schemas-microsoft-com:vml", "shape"); + private static final String COMMENT_SHAPE_TYPE_ID = "_x0000_t202"; // this ID value seems to have significance to Excel >= 2010; see https://issues.apache.org/bugzilla/show_bug.cgi?id=55409 /** * regexp to parse shape ids, in VML they have weird form of id="_x0000_s1026" @@ -190,7 +191,7 @@ public final class XSSFVMLDrawing extends POIXMLDocumentPart { _qnames.add(QNAME_SHAPE_LAYOUT); CTShapetype shapetype = CTShapetype.Factory.newInstance(); - _shapeTypeId = "_xssf_cell_comment"; + _shapeTypeId = COMMENT_SHAPE_TYPE_ID; shapetype.setId(_shapeTypeId); shapetype.setCoordsize("21600,21600"); shapetype.setSpt(202); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java index ae09af141..f90b48dfa 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java @@ -215,7 +215,15 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable srcRels = srcSheet.createDrawingPatriarch().getRelations(); for (POIXMLDocumentPart rel : srcRels) { PackageRelationship relation = rel.getPackageRelationship(); - clonedSheet - .createDrawingPatriarch() - .getPackagePart() + + clonedDg.addRelation(relation.getId(), rel); + + clonedDg + .getPackagePart() .addRelationship(relation.getTargetURI(), relation.getTargetMode(), relation.getRelationshipType(), relation.getId()); } @@ -751,8 +763,26 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable try next one + sheetNumber++; + continue outerloop; + } + } + + // no duplicate found => use this one + break; } XSSFSheet wrapper = (XSSFSheet)createRelationship(XSSFRelation.WORKSHEET, XSSFFactory.getInstance(), sheetNumber); @@ -821,6 +851,15 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable pivotTables) { this.pivotTables = pivotTables; } + + public XSSFWorkbookType getWorkbookType() { + return isMacroEnabled() ? XSSFWorkbookType.XLSM : XSSFWorkbookType.XLSX; + } + + /** + * Sets whether the workbook will be an .xlsx or .xlsm (macro-enabled) file. + */ + public void setWorkbookType(XSSFWorkbookType type) { + try { + getPackagePart().setContentType(type.getContentType()); + } catch (InvalidFormatException e) { + throw new POIXMLException(e); + } + } + + /** + * Adds a vbaProject.bin file to the workbook. This will change the workbook + * type if necessary. + * + * @throws IOException + */ + public void setVBAProject(InputStream vbaProjectStream) throws IOException { + if (!isMacroEnabled()) { + setWorkbookType(XSSFWorkbookType.XLSM); + } + + PackagePartName ppName; + try { + ppName = PackagingURIHelper.createPartName(XSSFRelation.VBA_MACROS.getDefaultFileName()); + } catch (InvalidFormatException e) { + throw new POIXMLException(e); + } + OPCPackage opc = getPackage(); + OutputStream outputStream; + if (!opc.containPart(ppName)) { + POIXMLDocumentPart relationship = createRelationship(XSSFRelation.VBA_MACROS, XSSFFactory.getInstance()); + outputStream = relationship.getPackagePart().getOutputStream(); + } else { + PackagePart part = opc.getPart(ppName); + outputStream = part.getOutputStream(); + } + try { + IOUtils.copy(vbaProjectStream, outputStream); + } finally { + IOUtils.closeQuietly(outputStream); + } + } + + /** + * Adds a vbaProject.bin file taken from another, given workbook to this one. + * @throws IOException + * @throws InvalidFormatException + */ + public void setVBAProject(XSSFWorkbook macroWorkbook) throws IOException, InvalidFormatException { + if (!macroWorkbook.isMacroEnabled()) { + return; + } + InputStream vbaProjectStream = XSSFRelation.VBA_MACROS.getContents(macroWorkbook.getCorePart()); + if (vbaProjectStream != null) { + setVBAProject(vbaProjectStream); + } + } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookType.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookType.java new file mode 100644 index 000000000..917d3d6da --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookType.java @@ -0,0 +1,45 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + + +/** + * Represents the two different kinds of XML-based OOXML document. + */ +public enum XSSFWorkbookType { + + XLSX(XSSFRelation.WORKBOOK.getContentType(), "xlsx"), + XLSM(XSSFRelation.MACROS_WORKBOOK.getContentType(), "xlsm"); + + private final String _contentType; + private final String _extension; + + private XSSFWorkbookType(String contentType, String extension) { + _contentType = contentType; + _extension = extension; + } + + public String getContentType() { + return _contentType; + } + + public String getExtension() { + return _extension; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java index 776210de3..a9d995fb7 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFFormulaUtils.java @@ -24,6 +24,7 @@ import org.apache.poi.ss.formula.FormulaRenderer; import org.apache.poi.ss.formula.FormulaType; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.Pxg; +import org.apache.poi.ss.formula.ptg.Pxg3D; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; @@ -125,9 +126,17 @@ public final class XSSFFormulaUtils { if (ptg instanceof Pxg) { Pxg pxg = (Pxg)ptg; if (pxg.getExternalWorkbookNumber() < 1) { - if (pxg.getSheetName().equals(oldName)) { + if (pxg.getSheetName() != null && + pxg.getSheetName().equals(oldName)) { pxg.setSheetName(newName); } + if (pxg instanceof Pxg3D) { + Pxg3D pxg3D = (Pxg3D)pxg; + if (pxg3D.getLastSheetName() != null && + pxg3D.getLastSheetName().equals(oldName)) { + pxg3D.setLastSheetName(newName); + } + } } } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/extractor/XWPFWordExtractor.java b/src/ooxml/java/org/apache/poi/xwpf/extractor/XWPFWordExtractor.java index afff770c7..ec701b7e3 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/extractor/XWPFWordExtractor.java +++ b/src/ooxml/java/org/apache/poi/xwpf/extractor/XWPFWordExtractor.java @@ -46,46 +46,47 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; * Helper class to extract text from an OOXML Word file */ public class XWPFWordExtractor extends POIXMLTextExtractor { - public static final XWPFRelation[] SUPPORTED_TYPES = new XWPFRelation[] { - XWPFRelation.DOCUMENT, XWPFRelation.TEMPLATE, - XWPFRelation.MACRO_DOCUMENT, - XWPFRelation.MACRO_TEMPLATE_DOCUMENT - }; - - private XWPFDocument document; - private boolean fetchHyperlinks = false; - - public XWPFWordExtractor(OPCPackage container) throws XmlException, OpenXML4JException, IOException { - this(new XWPFDocument(container)); - } - public XWPFWordExtractor(XWPFDocument document) { - super(document); - this.document = document; - } + public static final XWPFRelation[] SUPPORTED_TYPES = new XWPFRelation[]{ + XWPFRelation.DOCUMENT, XWPFRelation.TEMPLATE, + XWPFRelation.MACRO_DOCUMENT, + XWPFRelation.MACRO_TEMPLATE_DOCUMENT + }; + + private XWPFDocument document; + private boolean fetchHyperlinks = false; + + public XWPFWordExtractor(OPCPackage container) throws XmlException, OpenXML4JException, IOException { + this(new XWPFDocument(container)); + } + + public XWPFWordExtractor(XWPFDocument document) { + super(document); + this.document = document; + } + + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.err.println("Use:"); + System.err.println(" XWPFWordExtractor "); + System.exit(1); + } + POIXMLTextExtractor extractor = + new XWPFWordExtractor(POIXMLDocument.openPackage( + args[0] + )); + System.out.println(extractor.getText()); + extractor.close(); + } + + /** + * Should we also fetch the hyperlinks, when fetching + * the text content? Default is to only output the + * hyperlink label, and not the contents + */ + public void setFetchHyperlinks(boolean fetch) { + fetchHyperlinks = fetch; + } - /** - * Should we also fetch the hyperlinks, when fetching - * the text content? Default is to only output the - * hyperlink label, and not the contents - */ - public void setFetchHyperlinks(boolean fetch) { - fetchHyperlinks = fetch; - } - - public static void main(String[] args) throws Exception { - if(args.length < 1) { - System.err.println("Use:"); - System.err.println(" XWPFWordExtractor "); - System.exit(1); - } - POIXMLTextExtractor extractor = - new XWPFWordExtractor(POIXMLDocument.openPackage( - args[0] - )); - System.out.println(extractor.getText()); - extractor.close(); - } - public String getText() { StringBuffer text = new StringBuffer(); XWPFHeaderFooterPolicy hfPolicy = document.getHeaderFooterPolicy(); @@ -94,9 +95,9 @@ public class XWPFWordExtractor extends POIXMLTextExtractor { extractHeaders(text, hfPolicy); // Process all body elements - for (IBodyElement e : document.getBodyElements()){ - appendBodyElementText(text, e); - text.append('\n'); + for (IBodyElement e : document.getBodyElements()) { + appendBodyElementText(text, e); + text.append('\n'); } // Finish up with all the footers @@ -105,108 +106,108 @@ public class XWPFWordExtractor extends POIXMLTextExtractor { return text.toString(); } - public void appendBodyElementText(StringBuffer text, IBodyElement e){ - if (e instanceof XWPFParagraph){ - appendParagraphText(text, (XWPFParagraph)e); - } else if (e instanceof XWPFTable){ - appendTableText(text, (XWPFTable)e); - } else if (e instanceof XWPFSDT){ - text.append(((XWPFSDT)e).getContent().getText()); - } - } - - public void appendParagraphText(StringBuffer text, XWPFParagraph paragraph){ - try { - CTSectPr ctSectPr = null; - if (paragraph.getCTP().getPPr()!=null) { - ctSectPr = paragraph.getCTP().getPPr().getSectPr(); - } + public void appendBodyElementText(StringBuffer text, IBodyElement e) { + if (e instanceof XWPFParagraph) { + appendParagraphText(text, (XWPFParagraph) e); + } else if (e instanceof XWPFTable) { + appendTableText(text, (XWPFTable) e); + } else if (e instanceof XWPFSDT) { + text.append(((XWPFSDT) e).getContent().getText()); + } + } - XWPFHeaderFooterPolicy headerFooterPolicy = null; + public void appendParagraphText(StringBuffer text, XWPFParagraph paragraph) { + try { + CTSectPr ctSectPr = null; + if (paragraph.getCTP().getPPr() != null) { + ctSectPr = paragraph.getCTP().getPPr().getSectPr(); + } - if (ctSectPr!=null) { - headerFooterPolicy = new XWPFHeaderFooterPolicy(document, ctSectPr); - extractHeaders(text, headerFooterPolicy); - } + XWPFHeaderFooterPolicy headerFooterPolicy = null; + + if (ctSectPr != null) { + headerFooterPolicy = new XWPFHeaderFooterPolicy(document, ctSectPr); + extractHeaders(text, headerFooterPolicy); + } - for(IRunElement run : paragraph.getRuns()) { - text.append(run.toString()); - if(run instanceof XWPFHyperlinkRun && fetchHyperlinks) { - XWPFHyperlink link = ((XWPFHyperlinkRun)run).getHyperlink(document); - if(link != null) - text.append(" <" + link.getURL() + ">"); - } - } + for (IRunElement run : paragraph.getRuns()) { + text.append(run.toString()); + if (run instanceof XWPFHyperlinkRun && fetchHyperlinks) { + XWPFHyperlink link = ((XWPFHyperlinkRun) run).getHyperlink(document); + if (link != null) + text.append(" <" + link.getURL() + ">"); + } + } - // Add comments - XWPFCommentsDecorator decorator = new XWPFCommentsDecorator(paragraph, null); - String commentText = decorator.getCommentText(); - if (commentText.length() > 0){ - text.append(commentText).append('\n'); - } + // Add comments + XWPFCommentsDecorator decorator = new XWPFCommentsDecorator(paragraph, null); + String commentText = decorator.getCommentText(); + if (commentText.length() > 0) { + text.append(commentText).append('\n'); + } - // Do endnotes and footnotes - String footnameText = paragraph.getFootnoteText(); - if(footnameText != null && footnameText.length() > 0) { - text.append(footnameText + '\n'); - } + // Do endnotes and footnotes + String footnameText = paragraph.getFootnoteText(); + if (footnameText != null && footnameText.length() > 0) { + text.append(footnameText + '\n'); + } - if (ctSectPr!=null) { - extractFooters(text, headerFooterPolicy); - } - } catch (IOException e) { - throw new POIXMLException(e); - } catch (XmlException e) { - throw new POIXMLException(e); - } - - } + if (ctSectPr != null) { + extractFooters(text, headerFooterPolicy); + } + } catch (IOException e) { + throw new POIXMLException(e); + } catch (XmlException e) { + throw new POIXMLException(e); + } - private void appendTableText(StringBuffer text, XWPFTable table) { - //this works recursively to pull embedded tables from tables - for (XWPFTableRow row : table.getRows()) { - List cells = row.getTableICells(); - for (int i = 0; i < cells.size(); i++) { - ICell cell = cells.get(i); - if (cell instanceof XWPFTableCell) { - text.append(((XWPFTableCell)cell).getTextRecursively()); - } else if (cell instanceof XWPFSDTCell) { - text.append(((XWPFSDTCell)cell).getContent().getText()); - } - if (i < cells.size()-1) { - text.append("\t"); - } - } - text.append('\n'); - } - } - - private void extractFooters(StringBuffer text, XWPFHeaderFooterPolicy hfPolicy) { - if (hfPolicy == null) return; - - if(hfPolicy.getFirstPageFooter() != null) { - text.append( hfPolicy.getFirstPageFooter().getText() ); - } - if(hfPolicy.getEvenPageFooter() != null) { - text.append( hfPolicy.getEvenPageFooter().getText() ); - } - if(hfPolicy.getDefaultFooter() != null) { - text.append( hfPolicy.getDefaultFooter().getText() ); - } - } + } - private void extractHeaders(StringBuffer text, XWPFHeaderFooterPolicy hfPolicy) { - if (hfPolicy == null) return; - - if(hfPolicy.getFirstPageHeader() != null) { - text.append( hfPolicy.getFirstPageHeader().getText() ); - } - if(hfPolicy.getEvenPageHeader() != null) { - text.append( hfPolicy.getEvenPageHeader().getText() ); - } - if(hfPolicy.getDefaultHeader() != null) { - text.append( hfPolicy.getDefaultHeader().getText() ); - } - } + private void appendTableText(StringBuffer text, XWPFTable table) { + //this works recursively to pull embedded tables from tables + for (XWPFTableRow row : table.getRows()) { + List cells = row.getTableICells(); + for (int i = 0; i < cells.size(); i++) { + ICell cell = cells.get(i); + if (cell instanceof XWPFTableCell) { + text.append(((XWPFTableCell) cell).getTextRecursively()); + } else if (cell instanceof XWPFSDTCell) { + text.append(((XWPFSDTCell) cell).getContent().getText()); + } + if (i < cells.size() - 1) { + text.append("\t"); + } + } + text.append('\n'); + } + } + + private void extractFooters(StringBuffer text, XWPFHeaderFooterPolicy hfPolicy) { + if (hfPolicy == null) return; + + if (hfPolicy.getFirstPageFooter() != null) { + text.append(hfPolicy.getFirstPageFooter().getText()); + } + if (hfPolicy.getEvenPageFooter() != null) { + text.append(hfPolicy.getEvenPageFooter().getText()); + } + if (hfPolicy.getDefaultFooter() != null) { + text.append(hfPolicy.getDefaultFooter().getText()); + } + } + + private void extractHeaders(StringBuffer text, XWPFHeaderFooterPolicy hfPolicy) { + if (hfPolicy == null) return; + + if (hfPolicy.getFirstPageHeader() != null) { + text.append(hfPolicy.getFirstPageHeader().getText()); + } + if (hfPolicy.getEvenPageHeader() != null) { + text.append(hfPolicy.getEvenPageHeader().getText()); + } + if (hfPolicy.getDefaultHeader() != null) { + text.append(hfPolicy.getDefaultHeader().getText()); + } + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/model/XMLParagraph.java b/src/ooxml/java/org/apache/poi/xwpf/model/XMLParagraph.java index c7d4bc261..25aa7aab3 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/model/XMLParagraph.java +++ b/src/ooxml/java/org/apache/poi/xwpf/model/XMLParagraph.java @@ -22,16 +22,15 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; * Base class for XWPF paragraphs * * @author Yury Batrakov (batrakov at gmail.com) - * */ public class XMLParagraph { - protected CTP paragraph; - - public XMLParagraph(CTP paragraph) { - this.paragraph = paragraph; - } + protected CTP paragraph; - public CTP getCTP() { - return paragraph; - } + public XMLParagraph(CTP paragraph) { + this.paragraph = paragraph; + } + + public CTP getCTP() { + return paragraph; + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFCommentsDecorator.java b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFCommentsDecorator.java index 502a3b786..bf2b5e8f4 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFCommentsDecorator.java +++ b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFCommentsDecorator.java @@ -21,38 +21,36 @@ import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTMarkupRange; /** - * Decorator class for XWPFParagraph allowing to add comments + * Decorator class for XWPFParagraph allowing to add comments * found in paragraph to its text * * @author Yury Batrakov (batrakov at gmail.com) - * */ public class XWPFCommentsDecorator extends XWPFParagraphDecorator { - private StringBuffer commentText; - - public XWPFCommentsDecorator(XWPFParagraphDecorator nextDecorator) { - this(nextDecorator.paragraph, nextDecorator); - } + private StringBuffer commentText; - @SuppressWarnings("deprecation") - public XWPFCommentsDecorator(XWPFParagraph paragraph, XWPFParagraphDecorator nextDecorator) { - super(paragraph, nextDecorator); + public XWPFCommentsDecorator(XWPFParagraphDecorator nextDecorator) { + this(nextDecorator.paragraph, nextDecorator); + } - XWPFComment comment; - commentText = new StringBuffer(); + @SuppressWarnings("deprecation") + public XWPFCommentsDecorator(XWPFParagraph paragraph, XWPFParagraphDecorator nextDecorator) { + super(paragraph, nextDecorator); - for(CTMarkupRange anchor : paragraph.getCTP().getCommentRangeStartArray()) - { - if((comment = paragraph.getDocument().getCommentByID(anchor.getId().toString())) != null) - commentText.append("\tComment by " + comment.getAuthor()+": "+comment.getText()); - } - } + XWPFComment comment; + commentText = new StringBuffer(); - public String getCommentText() { - return commentText.toString(); - } - - public String getText() { - return super.getText() + commentText; - } + for (CTMarkupRange anchor : paragraph.getCTP().getCommentRangeStartArray()) { + if ((comment = paragraph.getDocument().getCommentByID(anchor.getId().toString())) != null) + commentText.append("\tComment by " + comment.getAuthor() + ": " + comment.getText()); + } + } + + public String getCommentText() { + return commentText.toString(); + } + + public String getText() { + return super.getText() + commentText; + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java index 15783163e..700645df7 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java +++ b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHeaderFooterPolicy.java @@ -45,7 +45,6 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.FtrDocument; import org.openxmlformats.schemas.wordprocessingml.x2006.main.HdrDocument; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.Enum; - import schemasMicrosoftComOfficeOffice.CTLock; import schemasMicrosoftComOfficeOffice.STConnectType; import schemasMicrosoftComVml.CTFormulas; @@ -61,10 +60,10 @@ import schemasMicrosoftComVml.STTrueFalse; /** * A .docx file can have no headers/footers, the same header/footer - * on each page, odd/even page footers, and optionally also - * a different header/footer on the first page. + * on each page, odd/even page footers, and optionally also + * a different header/footer on the first page. * This class handles sorting out what there is, and giving you - * the right headers and footers for the document. + * the right headers and footers for the document. */ public class XWPFHeaderFooterPolicy { public static final Enum DEFAULT = STHdrFtr.DEFAULT; @@ -84,8 +83,8 @@ public class XWPFHeaderFooterPolicy { /** * Figures out the policy for the given document, - * and creates any header and footer objects - * as required. + * and creates any header and footer objects + * as required. */ public XWPFHeaderFooterPolicy(XWPFDocument doc) throws IOException, XmlException { this(doc, doc.getDocument().getBody().getSectPr()); @@ -93,8 +92,8 @@ public class XWPFHeaderFooterPolicy { /** * Figures out the policy for the given document, - * and creates any header and footer objects - * as required. + * and creates any header and footer objects + * as required. */ public XWPFHeaderFooterPolicy(XWPFDocument doc, CTSectPr sectPr) throws IOException, XmlException { // Grab what headers and footers have been defined @@ -102,7 +101,7 @@ public class XWPFHeaderFooterPolicy { // doesn't seem that .docx properly supports that // feature of the file format yet this.doc = doc; - for(int i=0; i relations = doc.getRelations(); int i = 1; - for (Iterator it = relations.iterator(); it.hasNext() ; ) { + for (Iterator it = relations.iterator(); it.hasNext(); ) { POIXMLDocumentPart item = it.next(); if (item.getPackageRelationship().getRelationshipType().equals(relation.getRelation())) { - i++; + i++; } } return i; @@ -231,14 +229,14 @@ public class XWPFHeaderFooterPolicy { private CTHdrFtr buildFtr(Enum type, String pStyle, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) { //CTHdrFtr ftr = buildHdrFtr(pStyle, pars); // MB 24 May 2010 - CTHdrFtr ftr = buildHdrFtr(pStyle, pars, wrapper); // MB 24 May 2010 + CTHdrFtr ftr = buildHdrFtr(pStyle, pars, wrapper); // MB 24 May 2010 setFooterReference(type, wrapper); return ftr; } private CTHdrFtr buildHdr(Enum type, String pStyle, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) { //CTHdrFtr hdr = buildHdrFtr(pStyle, pars); // MB 24 May 2010 - CTHdrFtr hdr = buildHdrFtr(pStyle, pars, wrapper); // MB 24 May 2010 + CTHdrFtr hdr = buildHdrFtr(pStyle, pars, wrapper); // MB 24 May 2010 setHeaderReference(type, wrapper); return hdr; } @@ -246,13 +244,12 @@ public class XWPFHeaderFooterPolicy { private CTHdrFtr buildHdrFtr(String pStyle, XWPFParagraph[] paragraphs) { CTHdrFtr ftr = CTHdrFtr.Factory.newInstance(); if (paragraphs != null) { - for (int i = 0 ; i < paragraphs.length ; i++) { + for (int i = 0; i < paragraphs.length; i++) { CTP p = ftr.addNewP(); //ftr.setPArray(0, paragraphs[i].getCTP()); // MB 23 May 2010 - ftr.setPArray(i, paragraphs[i].getCTP()); // MB 23 May 2010 + ftr.setPArray(i, paragraphs[i].getCTP()); // MB 23 May 2010 } - } - else { + } else { CTP p = ftr.addNewP(); byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR(); byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault(); @@ -270,21 +267,20 @@ public class XWPFHeaderFooterPolicy { * and createFooter(int, XWPFParagraph[]) methods or the getXXXXXHeader/Footer methods where * headers or footers had been added to a document since it had been created/opened, returned * an object that contained no XWPFParagraph objects even if the header/footer itself did contain - * text. The reason was that this line of code; CTHdrFtr ftr = CTHdrFtr.Factory.newInstance(); + * text. The reason was that this line of code; CTHdrFtr ftr = CTHdrFtr.Factory.newInstance(); * created a brand new instance of the CTHDRFtr class which was then populated with data when * it should have recovered the CTHdrFtr object encapsulated within the XWPFHeaderFooter object - * that had previoulsy been instantiated in the createHeader(int, XWPFParagraph[]) or + * that had previoulsy been instantiated in the createHeader(int, XWPFParagraph[]) or * createFooter(int, XWPFParagraph[]) methods. */ private CTHdrFtr buildHdrFtr(String pStyle, XWPFParagraph[] paragraphs, XWPFHeaderFooter wrapper) { CTHdrFtr ftr = wrapper._getHdrFtr(); if (paragraphs != null) { - for (int i = 0 ; i < paragraphs.length ; i++) { + for (int i = 0; i < paragraphs.length; i++) { CTP p = ftr.addNewP(); ftr.setPArray(i, paragraphs[i].getCTP()); } - } - else { + } else { CTP p = ftr.addNewP(); byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR(); byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault(); @@ -330,60 +326,70 @@ public class XWPFHeaderFooterPolicy { public XWPFHeader getFirstPageHeader() { return firstPageHeader; } + public XWPFFooter getFirstPageFooter() { return firstPageFooter; } + /** * Returns the odd page header. This is - * also the same as the default one... + * also the same as the default one... */ public XWPFHeader getOddPageHeader() { return defaultHeader; } + /** * Returns the odd page footer. This is - * also the same as the default one... + * also the same as the default one... */ public XWPFFooter getOddPageFooter() { return defaultFooter; } + public XWPFHeader getEvenPageHeader() { return evenPageHeader; } + public XWPFFooter getEvenPageFooter() { return evenPageFooter; } + public XWPFHeader getDefaultHeader() { return defaultHeader; } + public XWPFFooter getDefaultFooter() { return defaultFooter; } /** * Get the header that applies to the given - * (1 based) page. + * (1 based) page. + * * @param pageNumber The one based page number */ public XWPFHeader getHeader(int pageNumber) { - if(pageNumber == 1 && firstPageHeader != null) { + if (pageNumber == 1 && firstPageHeader != null) { return firstPageHeader; } - if(pageNumber % 2 == 0 && evenPageHeader != null) { + if (pageNumber % 2 == 0 && evenPageHeader != null) { return evenPageHeader; } return defaultHeader; } + /** * Get the footer that applies to the given - * (1 based) page. + * (1 based) page. + * * @param pageNumber The one based page number */ public XWPFFooter getFooter(int pageNumber) { - if(pageNumber == 1 && firstPageFooter != null) { + if (pageNumber == 1 && firstPageFooter != null) { return firstPageFooter; } - if(pageNumber % 2 == 0 && evenPageFooter != null) { + if (pageNumber % 2 == 0 && evenPageFooter != null) { return evenPageFooter; } return defaultFooter; @@ -459,7 +465,7 @@ public class XWPFHeaderFooterPolicy { lock.setExt(STExt.EDIT); CTShape shape = group.addNewShape(); shape.setId("PowerPlusWaterMarkObject" + idx); - shape.setSpid("_x0000_s102" + (4+idx)); + shape.setSpid("_x0000_s102" + (4 + idx)); shape.setType("#_x0000_t136"); shape.setStyle("position:absolute;margin-left:0;margin-top:0;width:415pt;height:207.5pt;z-index:-251654144;mso-wrap-edited:f;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin"); shape.setWrapcoords("616 5068 390 16297 39 16921 -39 17155 7265 17545 7186 17467 -39 17467 18904 17467 10507 17467 8710 17545 18904 17077 18787 16843 18358 16297 18279 12554 19178 12476 20701 11774 20779 11228 21131 10059 21248 8811 21248 7563 20975 6316 20935 5380 19490 5146 14022 5068 2616 5068"); diff --git a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHyperlinkDecorator.java b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHyperlinkDecorator.java index d8120340f..27e8282ea 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHyperlinkDecorator.java +++ b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFHyperlinkDecorator.java @@ -23,50 +23,49 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText; /** - * Decorator class for XWPFParagraph allowing to add hyperlinks - * found in paragraph to its text. - * + * Decorator class for XWPFParagraph allowing to add hyperlinks + * found in paragraph to its text. + *

    * Note - adds the hyperlink at the end, not in the right place... - * + * * @deprecated Use {@link XWPFHyperlinkRun} instead */ @Deprecated public class XWPFHyperlinkDecorator extends XWPFParagraphDecorator { - private StringBuffer hyperlinkText; - - /** - * @param nextDecorator The next decorator to use - * @param outputHyperlinkUrls Should we output the links too, or just the link text? - */ - public XWPFHyperlinkDecorator(XWPFParagraphDecorator nextDecorator, boolean outputHyperlinkUrls) { - this(nextDecorator.paragraph, nextDecorator, outputHyperlinkUrls); - } - - /** - * @param prgrph The paragraph of text to work on - * @param outputHyperlinkUrls Should we output the links too, or just the link text? - */ - public XWPFHyperlinkDecorator(XWPFParagraph prgrph, XWPFParagraphDecorator nextDecorator, boolean outputHyperlinkUrls) { - super(prgrph, nextDecorator); - - hyperlinkText = new StringBuffer(); - - // loop over hyperlink anchors - for(CTHyperlink link : paragraph.getCTP().getHyperlinkArray()){ - for (CTR r : link.getRArray()) { - // Loop over text runs - for (CTText text : r.getTArray()){ - hyperlinkText.append(text.getStringValue()); - } - } - if(outputHyperlinkUrls && paragraph.getDocument().getHyperlinkByID(link.getId()) != null) { - hyperlinkText.append(" <"+paragraph.getDocument().getHyperlinkByID(link.getId()).getURL()+">"); - } - } - } - - public String getText() - { - return super.getText() + hyperlinkText; - } + private StringBuffer hyperlinkText; + + /** + * @param nextDecorator The next decorator to use + * @param outputHyperlinkUrls Should we output the links too, or just the link text? + */ + public XWPFHyperlinkDecorator(XWPFParagraphDecorator nextDecorator, boolean outputHyperlinkUrls) { + this(nextDecorator.paragraph, nextDecorator, outputHyperlinkUrls); + } + + /** + * @param prgrph The paragraph of text to work on + * @param outputHyperlinkUrls Should we output the links too, or just the link text? + */ + public XWPFHyperlinkDecorator(XWPFParagraph prgrph, XWPFParagraphDecorator nextDecorator, boolean outputHyperlinkUrls) { + super(prgrph, nextDecorator); + + hyperlinkText = new StringBuffer(); + + // loop over hyperlink anchors + for (CTHyperlink link : paragraph.getCTP().getHyperlinkArray()) { + for (CTR r : link.getRArray()) { + // Loop over text runs + for (CTText text : r.getTArray()) { + hyperlinkText.append(text.getStringValue()); + } + } + if (outputHyperlinkUrls && paragraph.getDocument().getHyperlinkByID(link.getId()) != null) { + hyperlinkText.append(" <" + paragraph.getDocument().getHyperlinkByID(link.getId()).getURL() + ">"); + } + } + } + + public String getText() { + return super.getText() + hyperlinkText; + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFParagraphDecorator.java b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFParagraphDecorator.java index 3946b22b8..46636c3ef 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/model/XWPFParagraphDecorator.java +++ b/src/ooxml/java/org/apache/poi/xwpf/model/XWPFParagraphDecorator.java @@ -22,22 +22,22 @@ import org.apache.poi.xwpf.usermodel.XWPFParagraph; * Base decorator class for XWPFParagraph */ public abstract class XWPFParagraphDecorator { - protected XWPFParagraph paragraph; - protected XWPFParagraphDecorator nextDecorator; - - public XWPFParagraphDecorator(XWPFParagraph paragraph) { - this(paragraph, null); - } - - public XWPFParagraphDecorator(XWPFParagraph paragraph, XWPFParagraphDecorator nextDecorator) { - this.paragraph = paragraph; - this.nextDecorator = nextDecorator; - } - - public String getText() { - if(nextDecorator != null) { - return nextDecorator.getText(); - } - return paragraph.getText(); - } + protected XWPFParagraph paragraph; + protected XWPFParagraphDecorator nextDecorator; + + public XWPFParagraphDecorator(XWPFParagraph paragraph) { + this(paragraph, null); + } + + public XWPFParagraphDecorator(XWPFParagraph paragraph, XWPFParagraphDecorator nextDecorator) { + this.paragraph = paragraph; + this.nextDecorator = nextDecorator; + } + + public String getText() { + if (nextDecorator != null) { + return nextDecorator.getText(); + } + return paragraph.getText(); + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/package.html b/src/ooxml/java/org/apache/poi/xwpf/package.html index 8c6c70d9e..0a5955646 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/package.html +++ b/src/ooxml/java/org/apache/poi/xwpf/package.html @@ -19,9 +19,9 @@ --> -

    This package contains classes for handling Microsoft .docx - Word Processing files, known in POI as XWPF (XML Word Processing - Format). -

    +

    This package contains classes for handling Microsoft .docx + Word Processing files, known in POI as XWPF (XML Word Processing + Format). +

    diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/AbstractXWPFSDT.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/AbstractXWPFSDT.java index e69b0244e..0e275460a 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/AbstractXWPFSDT.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/AbstractXWPFSDT.java @@ -13,102 +13,92 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -import java.util.List; - -import org.apache.poi.POIXMLDocumentPart; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtPr; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString; - -/** - * Experimental abstract class that is a base for XWPFSDT and XWPFSDTCell - * - * WARNING - APIs expected to change rapidly. - * - * These classes have so far been built only for read-only processing. - * - */ -public abstract class AbstractXWPFSDT implements ISDTContents { - private final String title; - private final String tag; - private final IBody part; - - @SuppressWarnings("deprecation") - public AbstractXWPFSDT(CTSdtPr pr, IBody part){ - - CTString[] aliases = pr.getAliasArray(); - if (aliases != null && aliases.length > 0){ - title = aliases[0].getVal(); - } else { - title = ""; - } - CTString[] tags = pr.getTagArray(); - if (tags != null && tags.length > 0){ - tag = tags[0].getVal(); - } else { - tag = ""; - } - this.part = part; - - } - - /** - * - * @return first SDT Title - */ - public String getTitle(){ - return title; - } - - /** - * - * @return first SDT Tag - */ - public String getTag(){ - return tag; - } - - /** - * - * @return the content object - */ - public abstract ISDTContent getContent(); - - /** - * - * @return null - */ - public IBody getBody() { - return null; - } - - /** - * - * @return document part - */ - public POIXMLDocumentPart getPart() { - return part.getPart(); - } - - /** - * - * @return partType - */ - public BodyType getPartType() { - return BodyType.CONTENTCONTROL; - } - - /** - * - * @return element type - */ - public BodyElementType getElementType() { - return BodyElementType.CONTENTCONTROL; - } - - public XWPFDocument getDocument() { - return part.getXWPFDocument(); - } -} +==================================================================== */ +package org.apache.poi.xwpf.usermodel; + +import org.apache.poi.POIXMLDocumentPart; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString; + +/** + * Experimental abstract class that is a base for XWPFSDT and XWPFSDTCell + *

    + * WARNING - APIs expected to change rapidly. + *

    + * These classes have so far been built only for read-only processing. + */ +public abstract class AbstractXWPFSDT implements ISDTContents { + private final String title; + private final String tag; + private final IBody part; + + @SuppressWarnings("deprecation") + public AbstractXWPFSDT(CTSdtPr pr, IBody part) { + + CTString[] aliases = pr.getAliasArray(); + if (aliases != null && aliases.length > 0) { + title = aliases[0].getVal(); + } else { + title = ""; + } + CTString[] tags = pr.getTagArray(); + if (tags != null && tags.length > 0) { + tag = tags[0].getVal(); + } else { + tag = ""; + } + this.part = part; + + } + + /** + * @return first SDT Title + */ + public String getTitle() { + return title; + } + + /** + * @return first SDT Tag + */ + public String getTag() { + return tag; + } + + /** + * @return the content object + */ + public abstract ISDTContent getContent(); + + /** + * @return null + */ + public IBody getBody() { + return null; + } + + /** + * @return document part + */ + public POIXMLDocumentPart getPart() { + return part.getPart(); + } + + /** + * @return partType + */ + public BodyType getPartType() { + return BodyType.CONTENTCONTROL; + } + + /** + * @return element type + */ + public BodyElementType getElementType() { + return BodyElementType.CONTENTCONTROL; + } + + public XWPFDocument getDocument() { + return part.getXWPFDocument(); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BodyElementType.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BodyElementType.java index 160c637bd..5a1df0e21 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BodyElementType.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BodyElementType.java @@ -21,15 +21,14 @@ package org.apache.poi.xwpf.usermodel; *

    * 9 Jan 2010 *

    - *

    - * // TODO insert Javadoc here! - *

    - * @author epp - * - */ -public enum BodyElementType { - CONTENTCONTROL, - PARAGRAPH, - TABLE, - -} + *

    + * // TODO insert Javadoc here! + *

    + * + * @author epp + */ +public enum BodyElementType { + CONTENTCONTROL, + PARAGRAPH, + TABLE, +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java index 48ea33d2a..b7937e528 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Borders.java @@ -29,14 +29,15 @@ import java.util.Map; * *
  • Art borders: which specify a repeated image to be used * when drawing a border around the specified object. Line borders may be - * specified on any object which allows a border, however, art borders may only - * be used as a border at the page level - the borders under the pgBorders - * element - *
  • - * - * @author Gisella Bronzetti - */ -public enum Borders { + * specified on any object which allows a border, however, art borders may only + * be used as a border at the page level - the borders under the pgBorders + * element + * + * + * + * @author Gisella Bronzetti + */ +public enum Borders { NIL(1), @@ -596,31 +597,32 @@ public enum Borders { ZANY_TRIANGLES(189), ZIG_ZAG(190), - - ZIG_ZAG_STITCH(191); - - private final int value; - - private Borders(int val) { - value = val; - } - - public int getValue() { - return value; - } - - private static Map imap = new HashMap(); - static { - for (Borders p : values()) { - imap.put(Integer.valueOf(p.getValue()), p); - } - } - - public static Borders valueOf(int type) { - Borders pBorder = imap.get(Integer.valueOf(type)); - if (pBorder == null) { - throw new IllegalArgumentException("Unknown paragraph border: " + type); - } - return pBorder; - } -} + + ZIG_ZAG_STITCH(191); + + private static Map imap = new HashMap(); + + static { + for (Borders p : values()) { + imap.put(Integer.valueOf(p.getValue()), p); + } + } + + private final int value; + + private Borders(int val) { + value = val; + } + + public static Borders valueOf(int type) { + Borders pBorder = imap.get(Integer.valueOf(type)); + if (pBorder == null) { + throw new IllegalArgumentException("Unknown paragraph border: " + type); + } + return pBorder; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakClear.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakClear.java index 8ad98905e..4fbef1d20 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakClear.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakClear.java @@ -20,23 +20,23 @@ import java.util.HashMap; import java.util.Map; /** - * Specifies the set of possible restart locations which may be used as to - * determine the next available line when a break's type attribute has a value - * of textWrapping. - * - * @author Gisella Bronzetti - */ -public enum BreakClear { + * Specifies the set of possible restart locations which may be used as to + * determine the next available line when a break's type attribute has a value + * of textWrapping. + * + * @author Gisella Bronzetti + */ +public enum BreakClear { /** * Specifies that the text wrapping break shall advance the text to the next - * line in the WordprocessingML document, regardless of its position left to - * right or the presence of any floating objects which intersect with the - * line, - * - * This is the setting for a typical line break in a document. - */ - + * line in the WordprocessingML document, regardless of its position left to + * right or the presence of any floating objects which intersect with the + * line, + *

    + * This is the setting for a typical line break in a document. + */ + NONE(1), /** @@ -80,31 +80,32 @@ public enum BreakClear { * Specifies that the text wrapping break shall advance the text to the next * line in the WordprocessingML document which spans the full width of the * line. - */ - ALL(4); - - private final int value; - - private BreakClear(int val) { - value = val; - } - - public int getValue() { - return value; - } - - private static Map imap = new HashMap(); - static { - for (BreakClear p : values()) { - imap.put(new Integer(p.getValue()), p); - } - } - - public static BreakClear valueOf(int type) { - BreakClear bType = imap.get(new Integer(type)); - if (bType == null) - throw new IllegalArgumentException("Unknown break clear type: " - + type); - return bType; - } -} + */ + ALL(4); + + private static Map imap = new HashMap(); + + static { + for (BreakClear p : values()) { + imap.put(new Integer(p.getValue()), p); + } + } + + private final int value; + + private BreakClear(int val) { + value = val; + } + + public static BreakClear valueOf(int type) { + BreakClear bType = imap.get(new Integer(type)); + if (bType == null) + throw new IllegalArgumentException("Unknown break clear type: " + + type); + return bType; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakType.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakType.java index 60b35225b..94cddab50 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakType.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/BreakType.java @@ -21,18 +21,18 @@ import java.util.Map; /** * Specifies the possible types of break characters in a WordprocessingML - * document. - * The break type determines the next location where text shall be - * placed after this manual break is applied to the text contents - * - * @author Gisella Bronzetti - */ -public enum BreakType { - - - /** - * Specifies that the current break shall restart itself on the next page of - * the document when the document is displayed in page view. + * document. + * The break type determines the next location where text shall be + * placed after this manual break is applied to the text contents + * + * @author Gisella Bronzetti + */ +public enum BreakType { + + + /** + * Specifies that the current break shall restart itself on the next page of + * the document when the document is displayed in page view. */ PAGE(1), @@ -53,31 +53,32 @@ public enum BreakType { * the document when the document is displayed in page view. * The determine of the next line shall be done subject to the value of the clear * attribute on the specified break character. - */ - TEXT_WRAPPING(3); - - private final int value; - - private BreakType(int val) { - value = val; - } - - public int getValue() { - return value; - } - - private static Map imap = new HashMap(); - static { - for (BreakType p : values()) { - imap.put(new Integer(p.getValue()), p); - } - } - - public static BreakType valueOf(int type) { - BreakType bType = imap.get(new Integer(type)); - if (bType == null) - throw new IllegalArgumentException("Unknown break type: " - + type); - return bType; - } -} + */ + TEXT_WRAPPING(3); + + private static Map imap = new HashMap(); + + static { + for (BreakType p : values()) { + imap.put(new Integer(p.getValue()), p); + } + } + + private final int value; + + private BreakType(int val) { + value = val; + } + + public static BreakType valueOf(int type) { + BreakType bType = imap.get(new Integer(type)); + if (bType == null) + throw new IllegalArgumentException("Unknown break type: " + + type); + return bType; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Document.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Document.java index 2df6f577f..077697a16 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/Document.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/Document.java @@ -14,31 +14,45 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -public interface Document { - /** Extended windows meta file */ - public static final int PICTURE_TYPE_EMF = 2; - - /** Windows Meta File */ - public static final int PICTURE_TYPE_WMF = 3; - - /** Mac PICT format */ - public static final int PICTURE_TYPE_PICT = 4; - - /** JPEG format */ - public static final int PICTURE_TYPE_JPEG = 5; - - /** PNG format */ - public static final int PICTURE_TYPE_PNG = 6; - - /** Device independent bitmap */ - public static final int PICTURE_TYPE_DIB = 7; - - /** GIF image format */ - public static final int PICTURE_TYPE_GIF = 8; - - /** +package org.apache.poi.xwpf.usermodel; + +public interface Document { + /** + * Extended windows meta file + */ + public static final int PICTURE_TYPE_EMF = 2; + + /** + * Windows Meta File + */ + public static final int PICTURE_TYPE_WMF = 3; + + /** + * Mac PICT format + */ + public static final int PICTURE_TYPE_PICT = 4; + + /** + * JPEG format + */ + public static final int PICTURE_TYPE_JPEG = 5; + + /** + * PNG format + */ + public static final int PICTURE_TYPE_PNG = 6; + + /** + * Device independent bitmap + */ + public static final int PICTURE_TYPE_DIB = 7; + + /** + * GIF image format + */ + public static final int PICTURE_TYPE_GIF = 8; + + /** * Tag Image File (.tiff) */ public static final int PICTURE_TYPE_TIFF = 9; diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java index e03588811..6e9ce05e4 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBody.java @@ -27,64 +27,68 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; /** *

    An IBody represents the different parts of the document which - * can contain collections of Paragraphs and Tables. It provides a - * common way to work with these and their contents.

    - *

    Typically, this is something like a XWPFDocument, or one of - * the parts in it like XWPFHeader, XWPFFooter, XWPFTableCell - *

    - */ -public interface IBody { + * can contain collections of Paragraphs and Tables. It provides a + * common way to work with these and their contents.

    + *

    Typically, this is something like a XWPFDocument, or one of + * the parts in it like XWPFHeader, XWPFFooter, XWPFTableCell + *

    + */ +public interface IBody { /** - * returns the Part, to which the body belongs, which you need for adding relationship to other parts - * Actually it is needed of the class XWPFTableCell. Because you have to know to which part the tableCell - * belongs. - * @return the Part, to which the body belongs - */ - public POIXMLDocumentPart getPart(); - - /** - * get the PartType of the body, for example - * DOCUMENT, HEADER, FOOTER, FOOTNOTE, - * @return the PartType of the body - */ - public BodyType getPartType(); - - /** - * Returns an Iterator with paragraphs and tables, - * in the order that they occur in the text. - */ - public List getBodyElements(); - - /** - * Returns the paragraph(s) that holds - * the text of the header or footer. - */ - public List getParagraphs(); - - /** - * Return the table(s) that holds the text - * of the IBodyPart, for complex cases - * where a paragraph isn't used. - */ - public List getTables(); - - /** - * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer - * the method will return this paragraph - * if there is no corresponding {@link XWPFParagraph} the method will return null - * @param p is instance of CTP and is searching for an XWPFParagraph - * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer - * XWPFParagraph with the correspondig CTP p - */ - public XWPFParagraph getParagraph(CTP p); - - /** - * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header - * the method will return this table - * if there is no corresponding {@link XWPFTable} the method will return null - * @param ctTable - */ - public XWPFTable getTable(CTTbl ctTable); + * returns the Part, to which the body belongs, which you need for adding relationship to other parts + * Actually it is needed of the class XWPFTableCell. Because you have to know to which part the tableCell + * belongs. + * + * @return the Part, to which the body belongs + */ + public POIXMLDocumentPart getPart(); + + /** + * get the PartType of the body, for example + * DOCUMENT, HEADER, FOOTER, FOOTNOTE, + * + * @return the PartType of the body + */ + public BodyType getPartType(); + + /** + * Returns an Iterator with paragraphs and tables, + * in the order that they occur in the text. + */ + public List getBodyElements(); + + /** + * Returns the paragraph(s) that holds + * the text of the header or footer. + */ + public List getParagraphs(); + + /** + * Return the table(s) that holds the text + * of the IBodyPart, for complex cases + * where a paragraph isn't used. + */ + public List getTables(); + + /** + * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer + * the method will return this paragraph + * if there is no corresponding {@link XWPFParagraph} the method will return null + * + * @param p is instance of CTP and is searching for an XWPFParagraph + * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer + * XWPFParagraph with the correspondig CTP p + */ + public XWPFParagraph getParagraph(CTP p); + + /** + * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header + * the method will return this table + * if there is no corresponding {@link XWPFTable} the method will return null + * + * @param ctTable + */ + public XWPFTable getTable(CTTbl ctTable); /** * Returns the paragraph that of position pos @@ -94,32 +98,36 @@ public interface IBody { /** * Returns the table at position pos */ - public XWPFTable getTableArray(int pos); - - /** - *inserts a new paragraph at position of the cursor - * @param cursor - */ - public XWPFParagraph insertNewParagraph(XmlCursor cursor); - - /** - * inserts a new Table at the cursor position. - * @param cursor - */ - public XWPFTable insertNewTbl(XmlCursor cursor); - - /** - * inserts a new Table at position pos - * @param pos - * @param table - */ + public XWPFTable getTableArray(int pos); + + /** + * inserts a new paragraph at position of the cursor + * + * @param cursor + */ + public XWPFParagraph insertNewParagraph(XmlCursor cursor); + + /** + * inserts a new Table at the cursor position. + * + * @param cursor + */ + public XWPFTable insertNewTbl(XmlCursor cursor); + + /** + * inserts a new Table at position pos + * + * @param pos + * @param table + */ void insertTable(int pos, XWPFTable table); - - /** - * returns the TableCell to which the Table belongs - * @param cell - */ - public XWPFTableCell getTableCell(CTTc cell); + + /** + * returns the TableCell to which the Table belongs + * + * @param cell + */ + public XWPFTableCell getTableCell(CTTc cell); /** * Return XWPFDocument diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java index 70009be3b..312ea493f 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IBodyElement.java @@ -18,15 +18,18 @@ package org.apache.poi.xwpf.usermodel; import org.apache.poi.POIXMLDocumentPart; - -/** - * 9 Jan 2010 - * @author Philipp Epp - * - */ -public interface IBodyElement{ - IBody getBody(); - POIXMLDocumentPart getPart(); - BodyType getPartType(); - BodyElementType getElementType(); -} + +/** + * 9 Jan 2010 + * + * @author Philipp Epp + */ +public interface IBodyElement { + IBody getBody(); + + POIXMLDocumentPart getPart(); + + BodyType getPartType(); + + BodyElementType getElementType(); +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ICell.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ICell.java index cf32924b8..0ac12c793 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ICell.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ICell.java @@ -15,13 +15,13 @@ limitations under the License. ==================================================================== */ package org.apache.poi.xwpf.usermodel; - -/** - * Interface for anything that can be at a table cell level: - * {@link XWPFTableCell}, {@link XWPFSDTCell} - *

    - * Schematically something like this: - * <tr><tc/><tc/><sdt><tc/></sdt></tr> - */ -public interface ICell { -} + +/** + * Interface for anything that can be at a table cell level: + * {@link XWPFTableCell}, {@link XWPFSDTCell} + *

    + * Schematically something like this: + * <tr><tc/><tc/><sdt><tc/></sdt></tr> + */ +public interface ICell { +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IRunBody.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IRunBody.java index 3ea4acabe..fea7856d1 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IRunBody.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IRunBody.java @@ -22,10 +22,11 @@ import org.apache.poi.wp.usermodel.Paragraph; /** * Simple interface describing both {@link XWPFParagraph} * and {@link XWPFSDT} - * + *

    * TODO Should this be based on / extend {@link Paragraph}? */ public interface IRunBody { - public XWPFDocument getDocument(); - public POIXMLDocumentPart getPart(); + public XWPFDocument getDocument(); + + public POIXMLDocumentPart getPart(); } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IRunElement.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IRunElement.java index f11b46a13..e8d1b83e7 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/IRunElement.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/IRunElement.java @@ -20,11 +20,10 @@ import org.apache.poi.wp.usermodel.CharacterRun; /** * Common interface for things that can occur - * where a run (text with common stylings) can, - * eg {@link XWPFRun} or {@link XWPFSDT}. + * where a run (text with common stylings) can, + * eg {@link XWPFRun} or {@link XWPFSDT}. * TODO More methods to follow shortly! - * + *

    * TODO Make this based on {@link CharacterRun} */ -public interface IRunElement { -} \ No newline at end of file +public interface IRunElement {} \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContent.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContent.java index 25599d7e6..5493ff3bd 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContent.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContent.java @@ -15,21 +15,20 @@ limitations under the License. ==================================================================== */ package org.apache.poi.xwpf.usermodel; - - -/** - * Experimental interface to offer rudimentary read-only processing of - * of the contentblock of an SDT/ContentControl. - * - * - * - * WARNING - APIs expected to change rapidly - * - */ -public interface ISDTContent { - - public String getText(); - - public String toString(); - + + +/** + * Experimental interface to offer rudimentary read-only processing of + * of the contentblock of an SDT/ContentControl. + *

    + *

    + *

    + * WARNING - APIs expected to change rapidly + */ +public interface ISDTContent { + + public String getText(); + + public String toString(); + } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContents.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContents.java index 40776e218..66922b837 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContents.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ISDTContents.java @@ -18,8 +18,8 @@ package org.apache.poi.xwpf.usermodel; /** * Interface for anything that can be within an SDT: - * {@link XWPFRun}, {@link XWPFTable}, {@link XWPFParagraph}, - * {@link XWPFSDT} etc + * {@link XWPFRun}, {@link XWPFTable}, {@link XWPFParagraph}, + * {@link XWPFSDT} etc */ public interface ISDTContents { } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/LineSpacingRule.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/LineSpacingRule.java index 166d8e701..b46c53206 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/LineSpacingRule.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/LineSpacingRule.java @@ -19,13 +19,13 @@ package org.apache.poi.xwpf.usermodel; import java.util.HashMap; import java.util.Map; -/** - * Specifies the logic which shall be used to calculate the line spacing of the - * parent object when it is displayed in the document. - * - * @author Gisella Bronzetti - */ -public enum LineSpacingRule { +/** + * Specifies the logic which shall be used to calculate the line spacing of the + * parent object when it is displayed in the document. + * + * @author Gisella Bronzetti + */ +public enum LineSpacingRule { /** * Specifies that the line spacing of the parent object shall be @@ -45,31 +45,32 @@ public enum LineSpacingRule { /** * Specifies that the height of the line shall be at least the value * specified, but may be expanded to fit its content as needed. - */ - AT_LEAST(3); - - - private final int value; - - private LineSpacingRule(int val) { - value = val; - } - - public int getValue() { - return value; - } - - private static Map imap = new HashMap(); - static { - for (LineSpacingRule p : values()) { - imap.put(new Integer(p.getValue()), p); - } - } - - public static LineSpacingRule valueOf(int type) { - LineSpacingRule lineType = imap.get(new Integer(type)); - if (lineType == null) - throw new IllegalArgumentException("Unknown line type: " + type); - return lineType; - } -} + */ + AT_LEAST(3); + + + private static Map imap = new HashMap(); + + static { + for (LineSpacingRule p : values()) { + imap.put(new Integer(p.getValue()), p); + } + } + + private final int value; + + private LineSpacingRule(int val) { + value = val; + } + + public static LineSpacingRule valueOf(int type) { + LineSpacingRule lineType = imap.get(new Integer(type)); + if (lineType == null) + throw new IllegalArgumentException("Unknown line type: " + type); + return lineType; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java index 0585ecb4c..226d4095a 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/ParagraphAlignment.java @@ -37,30 +37,31 @@ public enum ParagraphAlignment { DISTRIBUTE(6), NUM_TAB(7), HIGH_KASHIDA(8), - LOW_KASHIDA(9), - THAI_DISTRIBUTE(10); - - private final int value; - - private ParagraphAlignment(int val){ - value = val; - } - - public int getValue(){ - return value; - } - - private static Map imap = new HashMap(); - static{ - for (ParagraphAlignment p : values()) { - imap.put(new Integer(p.getValue()), p); - } - } - - public static ParagraphAlignment valueOf(int type){ - ParagraphAlignment err = imap.get(new Integer(type)); - if(err == null) throw new IllegalArgumentException("Unknown paragraph alignment: " + type); - return err; - } - -} + LOW_KASHIDA(9), + THAI_DISTRIBUTE(10); + + private static Map imap = new HashMap(); + + static { + for (ParagraphAlignment p : values()) { + imap.put(new Integer(p.getValue()), p); + } + } + + private final int value; + + private ParagraphAlignment(int val) { + value = val; + } + + public static ParagraphAlignment valueOf(int type) { + ParagraphAlignment err = imap.get(new Integer(type)); + if (err == null) throw new IllegalArgumentException("Unknown paragraph alignment: " + type); + return err; + } + + public int getValue() { + return value; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/PositionInParagraph.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/PositionInParagraph.java index 5e387e7f8..4eebe412e 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/PositionInParagraph.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/PositionInParagraph.java @@ -17,49 +17,47 @@ package org.apache.poi.xwpf.usermodel; - -/** - * postion of a character in a paragrapho -* 1st RunPositon -* 2nd TextPosition -* 3rd CharacterPosition -* -* -*/ -public class PositionInParagraph { - private int posRun = 0, posText = 0, posChar = 0; - - public PositionInParagraph(){ - } - - public PositionInParagraph(int posRun, int posText, int posChar){ - this.posRun=posRun; - this.posChar=posChar; - this.posText= posText; - } - - public int getRun() { - return posRun; - } - - public void setRun(int beginRun) { - this.posRun = beginRun; - } - - public int getText() { - return posText; - } - - public void setText(int beginText) { - this.posText = beginText; - } - - public int getChar() { - return posChar; - } - - public void setChar(int beginChar) { - this.posChar = beginChar; - } - -} + +/** + * postion of a character in a paragrapho + * 1st RunPositon + * 2nd TextPosition + * 3rd CharacterPosition + */ +public class PositionInParagraph { + private int posRun = 0, posText = 0, posChar = 0; + + public PositionInParagraph() { + } + + public PositionInParagraph(int posRun, int posText, int posChar) { + this.posRun = posRun; + this.posChar = posChar; + this.posText = posText; + } + + public int getRun() { + return posRun; + } + + public void setRun(int beginRun) { + this.posRun = beginRun; + } + + public int getText() { + return posText; + } + + public void setText(int beginText) { + this.posText = beginText; + } + + public int getChar() { + return posChar; + } + + public void setChar(int beginChar) { + this.posChar = beginChar; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TOC.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TOC.java index f144e624d..b7dc6ee2f 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TOC.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TOC.java @@ -38,85 +38,85 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabJc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabTlc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTheme; - -public class TOC { - - CTSdtBlock block; - - public TOC() { - this(CTSdtBlock.Factory.newInstance()); - } - - public TOC(CTSdtBlock block) { - this.block = block; - CTSdtPr sdtPr = block.addNewSdtPr(); - CTDecimalNumber id = sdtPr.addNewId(); - id.setVal(new BigInteger("4844945")); - sdtPr.addNewDocPartObj().addNewDocPartGallery().setVal("Table of contents"); - CTSdtEndPr sdtEndPr = block.addNewSdtEndPr(); - CTRPr rPr = sdtEndPr.addNewRPr(); - CTFonts fonts = rPr.addNewRFonts(); - fonts.setAsciiTheme(STTheme.MINOR_H_ANSI); - fonts.setEastAsiaTheme(STTheme.MINOR_H_ANSI); - fonts.setHAnsiTheme(STTheme.MINOR_H_ANSI); - fonts.setCstheme(STTheme.MINOR_BIDI); - rPr.addNewB().setVal(STOnOff.OFF); - rPr.addNewBCs().setVal(STOnOff.OFF); - rPr.addNewColor().setVal("auto"); - rPr.addNewSz().setVal(new BigInteger("24")); - rPr.addNewSzCs().setVal(new BigInteger("24")); - CTSdtContentBlock content = block.addNewSdtContent(); - CTP p = content.addNewP(); - p.setRsidR("00EF7E24".getBytes()); - p.setRsidRDefault("00EF7E24".getBytes()); - p.addNewPPr().addNewPStyle().setVal("TOCHeading"); - p.addNewR().addNewT().setStringValue("Table of Contents"); - } - - @Internal - public CTSdtBlock getBlock() { - return this.block; - } - - public void addRow(int level, String title, int page, String bookmarkRef) { - CTSdtContentBlock contentBlock = this.block.getSdtContent(); - CTP p = contentBlock.addNewP(); - p.setRsidR("00EF7E24".getBytes()); - p.setRsidRDefault("00EF7E24".getBytes()); - CTPPr pPr = p.addNewPPr(); - pPr.addNewPStyle().setVal("TOC" + level); - CTTabs tabs = pPr.addNewTabs(); - CTTabStop tab = tabs.addNewTab(); - tab.setVal(STTabJc.RIGHT); - tab.setLeader(STTabTlc.DOT); - tab.setPos(new BigInteger("8290")); - pPr.addNewRPr().addNewNoProof(); - CTR run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewT().setStringValue(title); - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewTab(); - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewFldChar().setFldCharType(STFldCharType.BEGIN); - // pageref run - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - CTText text = run.addNewInstrText(); - text.setSpace(Space.PRESERVE); - // bookmark reference - text.setStringValue(" PAGEREF _Toc" + bookmarkRef + " \\h "); - p.addNewR().addNewRPr().addNewNoProof(); - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewFldChar().setFldCharType(STFldCharType.SEPARATE); - // page number run - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewT().setStringValue(Integer.valueOf(page).toString()); - run = p.addNewR(); - run.addNewRPr().addNewNoProof(); - run.addNewFldChar().setFldCharType(STFldCharType.END); - } -} + +public class TOC { + + CTSdtBlock block; + + public TOC() { + this(CTSdtBlock.Factory.newInstance()); + } + + public TOC(CTSdtBlock block) { + this.block = block; + CTSdtPr sdtPr = block.addNewSdtPr(); + CTDecimalNumber id = sdtPr.addNewId(); + id.setVal(new BigInteger("4844945")); + sdtPr.addNewDocPartObj().addNewDocPartGallery().setVal("Table of contents"); + CTSdtEndPr sdtEndPr = block.addNewSdtEndPr(); + CTRPr rPr = sdtEndPr.addNewRPr(); + CTFonts fonts = rPr.addNewRFonts(); + fonts.setAsciiTheme(STTheme.MINOR_H_ANSI); + fonts.setEastAsiaTheme(STTheme.MINOR_H_ANSI); + fonts.setHAnsiTheme(STTheme.MINOR_H_ANSI); + fonts.setCstheme(STTheme.MINOR_BIDI); + rPr.addNewB().setVal(STOnOff.OFF); + rPr.addNewBCs().setVal(STOnOff.OFF); + rPr.addNewColor().setVal("auto"); + rPr.addNewSz().setVal(new BigInteger("24")); + rPr.addNewSzCs().setVal(new BigInteger("24")); + CTSdtContentBlock content = block.addNewSdtContent(); + CTP p = content.addNewP(); + p.setRsidR("00EF7E24".getBytes()); + p.setRsidRDefault("00EF7E24".getBytes()); + p.addNewPPr().addNewPStyle().setVal("TOCHeading"); + p.addNewR().addNewT().setStringValue("Table of Contents"); + } + + @Internal + public CTSdtBlock getBlock() { + return this.block; + } + + public void addRow(int level, String title, int page, String bookmarkRef) { + CTSdtContentBlock contentBlock = this.block.getSdtContent(); + CTP p = contentBlock.addNewP(); + p.setRsidR("00EF7E24".getBytes()); + p.setRsidRDefault("00EF7E24".getBytes()); + CTPPr pPr = p.addNewPPr(); + pPr.addNewPStyle().setVal("TOC" + level); + CTTabs tabs = pPr.addNewTabs(); + CTTabStop tab = tabs.addNewTab(); + tab.setVal(STTabJc.RIGHT); + tab.setLeader(STTabTlc.DOT); + tab.setPos(new BigInteger("8290")); + pPr.addNewRPr().addNewNoProof(); + CTR run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewT().setStringValue(title); + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewTab(); + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewFldChar().setFldCharType(STFldCharType.BEGIN); + // pageref run + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + CTText text = run.addNewInstrText(); + text.setSpace(Space.PRESERVE); + // bookmark reference + text.setStringValue(" PAGEREF _Toc" + bookmarkRef + " \\h "); + p.addNewR().addNewRPr().addNewNoProof(); + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewFldChar().setFldCharType(STFldCharType.SEPARATE); + // page number run + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewT().setStringValue(Integer.valueOf(page).toString()); + run = p.addNewR(); + run.addNewRPr().addNewNoProof(); + run.addNewFldChar().setFldCharType(STFldCharType.END); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextAlignment.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextAlignment.java index b2a8c13c7..7c1187df6 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextAlignment.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextAlignment.java @@ -17,25 +17,25 @@ package org.apache.poi.xwpf.usermodel; import java.util.HashMap; -import java.util.Map; - -/** - * Specifies all types of vertical alignment which are available to be applied to of all text - * on each line displayed within a paragraph. - * - * @author Gisella Bronzetti - */ -public enum TextAlignment { - /** - * Specifies that all text in the parent object shall be - * aligned to the top of each character when displayed - */ - TOP(1), - /** - * Specifies that all text in the parent object shall be - * aligned to the center of each character when displayed. - */ - CENTER(2), +import java.util.Map; + +/** + * Specifies all types of vertical alignment which are available to be applied to of all text + * on each line displayed within a paragraph. + * + * @author Gisella Bronzetti + */ +public enum TextAlignment { + /** + * Specifies that all text in the parent object shall be + * aligned to the top of each character when displayed + */ + TOP(1), + /** + * Specifies that all text in the parent object shall be + * aligned to the center of each character when displayed. + */ + CENTER(2), /** * Specifies that all text in the parent object shall be * aligned to the baseline of each character when displayed. @@ -44,34 +44,35 @@ public enum TextAlignment { /** * Specifies that all text in the parent object shall be * aligned to the bottom of each character when displayed. - */ - BOTTOM(4), - /** - * Specifies that all text in the parent object shall be - * aligned automatically when displayed. - */ - AUTO(5); - - private final int value; - - private TextAlignment(int val){ - value = val; - } - - public int getValue(){ - return value; - } - - private static Map imap = new HashMap(); - static{ - for (TextAlignment p : values()) { - imap.put(new Integer(p.getValue()), p); - } - } - - public static TextAlignment valueOf(int type){ - TextAlignment align = imap.get(new Integer(type)); - if(align == null) throw new IllegalArgumentException("Unknown text alignment: " + type); - return align; - } -} + */ + BOTTOM(4), + /** + * Specifies that all text in the parent object shall be + * aligned automatically when displayed. + */ + AUTO(5); + + private static Map imap = new HashMap(); + + static { + for (TextAlignment p : values()) { + imap.put(new Integer(p.getValue()), p); + } + } + + private final int value; + + private TextAlignment(int val) { + value = val; + } + + public static TextAlignment valueOf(int type) { + TextAlignment align = imap.get(new Integer(type)); + if (align == null) throw new IllegalArgumentException("Unknown text alignment: " + type); + return align; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextSegement.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextSegement.java index 23aa15808..44477daf8 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextSegement.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/TextSegement.java @@ -16,83 +16,84 @@ ==================================================================== */ package org.apache.poi.xwpf.usermodel; - -/** - * saves the begin and end position of a text in a Paragraph -*/ -public class TextSegement { - private PositionInParagraph beginPos; - private PositionInParagraph endPos; - - public TextSegement(){ - this.beginPos = new PositionInParagraph(); - this. endPos = new PositionInParagraph(); - } - - public TextSegement(int beginRun, int endRun, int beginText, int endText, int beginChar, int endChar){ - PositionInParagraph beginPos = new PositionInParagraph(beginRun, beginText, beginChar); - PositionInParagraph endPos = new PositionInParagraph(endRun, endText, endChar); - this.beginPos = beginPos; - this.endPos = endPos; - } - - public TextSegement(PositionInParagraph beginPos, PositionInParagraph endPos){ - this.beginPos = beginPos; - this.endPos = endPos; - } - - public PositionInParagraph getBeginPos(){ - return beginPos; - } - - public PositionInParagraph getEndPos(){ - return endPos; - } - - public int getBeginRun(){ - return beginPos.getRun(); - } - - public void setBeginRun(int beginRun){ - beginPos.setRun(beginRun); - } - - public int getBeginText(){ - return beginPos.getText(); - } - - public void setBeginText(int beginText){ - beginPos.setText(beginText); - } - - public int getBeginChar(){ - return beginPos.getChar(); - } - - public void setBeginChar(int beginChar){ - beginPos.setChar(beginChar); - } - public int getEndRun(){ - return endPos.getRun(); - } - - public void setEndRun(int endRun){ - endPos.setRun(endRun); - } - - public int getEndText(){ - return endPos.getText(); - } - - public void setEndText(int endText){ - endPos.setText(endText); - } - - public int getEndChar(){ - return endPos.getChar(); - } - - public void setEndChar(int endChar){ - endPos.setChar(endChar); - } -} + +/** + * saves the begin and end position of a text in a Paragraph + */ +public class TextSegement { + private PositionInParagraph beginPos; + private PositionInParagraph endPos; + + public TextSegement() { + this.beginPos = new PositionInParagraph(); + this.endPos = new PositionInParagraph(); + } + + public TextSegement(int beginRun, int endRun, int beginText, int endText, int beginChar, int endChar) { + PositionInParagraph beginPos = new PositionInParagraph(beginRun, beginText, beginChar); + PositionInParagraph endPos = new PositionInParagraph(endRun, endText, endChar); + this.beginPos = beginPos; + this.endPos = endPos; + } + + public TextSegement(PositionInParagraph beginPos, PositionInParagraph endPos) { + this.beginPos = beginPos; + this.endPos = endPos; + } + + public PositionInParagraph getBeginPos() { + return beginPos; + } + + public PositionInParagraph getEndPos() { + return endPos; + } + + public int getBeginRun() { + return beginPos.getRun(); + } + + public void setBeginRun(int beginRun) { + beginPos.setRun(beginRun); + } + + public int getBeginText() { + return beginPos.getText(); + } + + public void setBeginText(int beginText) { + beginPos.setText(beginText); + } + + public int getBeginChar() { + return beginPos.getChar(); + } + + public void setBeginChar(int beginChar) { + beginPos.setChar(beginChar); + } + + public int getEndRun() { + return endPos.getRun(); + } + + public void setEndRun(int endRun) { + endPos.setRun(endRun); + } + + public int getEndText() { + return endPos.getText(); + } + + public void setEndText(int endText) { + endPos.setText(endText); + } + + public int getEndChar() { + return endPos.getChar(); + } + + public void setEndChar(int endChar) { + endPos.setChar(endChar); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/UnderlinePatterns.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/UnderlinePatterns.java index 578dec332..9272ac060 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/UnderlinePatterns.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/UnderlinePatterns.java @@ -19,13 +19,13 @@ package org.apache.poi.xwpf.usermodel; import java.util.HashMap; import java.util.Map; -/** - * Specifies the types of patterns which may be used to create the underline - * applied beneath the text in a run. - * - * @author Gisella Bronzetti - */ -public enum UnderlinePatterns { +/** + * Specifies the types of patterns which may be used to create the underline + * applied beneath the text in a run. + * + * @author Gisella Bronzetti + */ +public enum UnderlinePatterns { /** * Specifies an underline consisting of a single line beneath all characters @@ -132,31 +132,32 @@ public enum UnderlinePatterns { /** * Specifies no underline beneath this run. - */ - NONE(18); - - private final int value; - - private UnderlinePatterns(int val) { - value = val; - } - - public int getValue() { - return value; - } - - private static Map imap = new HashMap(); - static { - for (UnderlinePatterns p : values()) { - imap.put(new Integer(p.getValue()), p); - } - } - - public static UnderlinePatterns valueOf(int type) { - UnderlinePatterns align = imap.get(new Integer(type)); - if (align == null) - throw new IllegalArgumentException("Unknown underline pattern: " - + type); - return align; - } -} + */ + NONE(18); + + private static Map imap = new HashMap(); + + static { + for (UnderlinePatterns p : values()) { + imap.put(new Integer(p.getValue()), p); + } + } + + private final int value; + + private UnderlinePatterns(int val) { + value = val; + } + + public static UnderlinePatterns valueOf(int type) { + UnderlinePatterns align = imap.get(new Integer(type)); + if (align == null) + throw new IllegalArgumentException("Unknown underline pattern: " + + type); + return align; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/VerticalAlign.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/VerticalAlign.java index 84ff62858..4114c1100 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/VerticalAlign.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/VerticalAlign.java @@ -21,13 +21,13 @@ import java.util.Map; /** * Specifies possible values for the alignment of the contents of this run in - * relation to the default appearance of the run's text. This allows the text to - * be repositioned as subscript or superscript without altering the font size of - * the run properties. - * - * @author Gisella Bronzetti - */ -public enum VerticalAlign { + * relation to the default appearance of the run's text. This allows the text to + * be repositioned as subscript or superscript without altering the font size of + * the run properties. + * + * @author Gisella Bronzetti + */ +public enum VerticalAlign { /** * Specifies that the text in the parent run shall be located at the @@ -44,31 +44,32 @@ public enum VerticalAlign { * Specifies that this text should be superscript. This setting shall raise * the text in this run above the baseline and change it to a smaller size, * if a smaller size is available. - */ - SUBSCRIPT(3); - - private final int value; - - private VerticalAlign(int val) { - value = val; - } - - public int getValue() { - return value; - } - - private static Map imap = new HashMap(); - static { - for (VerticalAlign p : values()) { - imap.put(new Integer(p.getValue()), p); - } - } - - public static VerticalAlign valueOf(int type) { - VerticalAlign align = imap.get(new Integer(type)); - if (align == null) - throw new IllegalArgumentException("Unknown vertical alignment: " - + type); - return align; - } -} + */ + SUBSCRIPT(3); + + private static Map imap = new HashMap(); + + static { + for (VerticalAlign p : values()) { + imap.put(new Integer(p.getValue()), p); + } + } + + private final int value; + + private VerticalAlign(int val) { + value = val; + } + + public static VerticalAlign valueOf(int type) { + VerticalAlign align = imap.get(new Integer(type)); + if (align == null) + throw new IllegalArgumentException("Unknown vertical alignment: " + + type); + return align; + } + + public int getValue() { + return value; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFAbstractNum.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFAbstractNum.java index 12d2d3a02..8d4886b90 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFAbstractNum.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFAbstractNum.java @@ -18,42 +18,43 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum; - -/** - * @author Philipp Epp - * - */ -public class XWPFAbstractNum { - private CTAbstractNum ctAbstractNum; - protected XWPFNumbering numbering; - - protected XWPFAbstractNum() { - this.ctAbstractNum = null; - this.numbering = null; - - } - public XWPFAbstractNum(CTAbstractNum abstractNum){ - this.ctAbstractNum = abstractNum; - } - - public XWPFAbstractNum(CTAbstractNum ctAbstractNum, XWPFNumbering numbering){ - this.ctAbstractNum = ctAbstractNum; - this.numbering = numbering; - } - public CTAbstractNum getAbstractNum(){ - return ctAbstractNum; - } - - public XWPFNumbering getNumbering(){ - return numbering; - } - - public CTAbstractNum getCTAbstractNum(){ - return ctAbstractNum; - } - - public void setNumbering(XWPFNumbering numbering){ - this.numbering = numbering; - } - -} + +/** + * @author Philipp Epp + */ +public class XWPFAbstractNum { + protected XWPFNumbering numbering; + private CTAbstractNum ctAbstractNum; + + protected XWPFAbstractNum() { + this.ctAbstractNum = null; + this.numbering = null; + + } + + public XWPFAbstractNum(CTAbstractNum abstractNum) { + this.ctAbstractNum = abstractNum; + } + + public XWPFAbstractNum(CTAbstractNum ctAbstractNum, XWPFNumbering numbering) { + this.ctAbstractNum = ctAbstractNum; + this.numbering = numbering; + } + + public CTAbstractNum getAbstractNum() { + return ctAbstractNum; + } + + public XWPFNumbering getNumbering() { + return numbering; + } + + public void setNumbering(XWPFNumbering numbering) { + this.numbering = numbering; + } + + public CTAbstractNum getCTAbstractNum() { + return ctAbstractNum; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComment.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComment.java index 84ebc36bb..627971b34 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComment.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFComment.java @@ -21,42 +21,35 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; /** * Sketch of XWPF comment class - * -* @author Yury Batrakov (batrakov at gmail.com) - * + * + * @author Yury Batrakov (batrakov at gmail.com) */ -public class XWPFComment -{ +public class XWPFComment { protected String id; protected String author; protected StringBuffer text; - + @SuppressWarnings("deprecation") - public XWPFComment(CTComment comment, XWPFDocument document) - { + public XWPFComment(CTComment comment, XWPFDocument document) { text = new StringBuffer(); id = comment.getId().toString(); author = comment.getAuthor(); - - for(CTP ctp : comment.getPArray()) - { + + for (CTP ctp : comment.getPArray()) { XWPFParagraph p = new XWPFParagraph(ctp, document); text.append(p.getText()); } } - - public String getId() - { + + public String getId() { return id; } - - public String getAuthor() - { + + public String getAuthor() { return author; } - - public String getText() - { + + public String getText() { return text.toString(); } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultParagraphStyle.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultParagraphStyle.java new file mode 100644 index 000000000..a430c87e5 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultParagraphStyle.java @@ -0,0 +1,42 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xwpf.usermodel; + +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr; + +/** + * Default Paragraph style, from which other styles will override + * TODO Share logic with {@link XWPFParagraph} which also uses CTPPr + */ +public class XWPFDefaultParagraphStyle { + private CTPPr ppr; + + public XWPFDefaultParagraphStyle(CTPPr ppr) { + this.ppr = ppr; + } + + protected CTPPr getPPr() { + return ppr; + } + + public int getSpacingAfter() { + if (ppr.isSetSpacing()) + return ppr.getSpacing().getAfter().intValue(); + return -1; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultRunStyle.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultRunStyle.java new file mode 100644 index 000000000..459335de6 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDefaultRunStyle.java @@ -0,0 +1,42 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xwpf.usermodel; + +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; + +/** + * Default Character Run style, from which other styles will override + * TODO Share logic with {@link XWPFRun} which also uses CTRPr + */ +public class XWPFDefaultRunStyle { + private CTRPr rpr; + + public XWPFDefaultRunStyle(CTRPr rpr) { + this.rpr = rpr; + } + + protected CTRPr getRPr() { + return rpr; + } + + public int getFontSize() { + if (rpr.isSetSz()) + return rpr.getSz().getVal().intValue() / 2; + return -1; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java index 9adc39704..9eabdebc8 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java @@ -76,23 +76,17 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.StylesDocument; /** *

    High(ish) level class for working with .docx files.

    - * + *

    *

    This class tries to hide some of the complexity - * of the underlying file format, but as it's not a - * mature and stable API yet, certain parts of the - * XML structure come through. You'll therefore almost - * certainly need to refer to the OOXML specifications - * from - * http://www.ecma-international.org/publications/standards/Ecma-376.htm - * at some point in your use.

    + * of the underlying file format, but as it's not a + * mature and stable API yet, certain parts of the + * XML structure come through. You'll therefore almost + * certainly need to refer to the OOXML specifications + * from + * http://www.ecma-international.org/publications/standards/Ecma-376.htm + * at some point in your use.

    */ public class XWPFDocument extends POIXMLDocument implements Document, IBody { - private CTDocument1 ctDocument; - private XWPFSettings settings; - /** - * Keeps track on all id-values used in this document and included parts, like headers, footers, etc. - */ - private IdentifierManager drawingIdManager = new IdentifierManager(1L,4294967295L); protected List footers = new ArrayList(); protected List headers = new ArrayList(); protected List comments = new ArrayList(); @@ -107,8 +101,15 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { protected XWPFNumbering numbering; protected XWPFStyles styles; protected XWPFFootnotes footnotes; - - /** Handles the joy of different headers/footers for different pages */ + private CTDocument1 ctDocument; + private XWPFSettings settings; + /** + * Keeps track on all id-values used in this document and included parts, like headers, footers, etc. + */ + private IdentifierManager drawingIdManager = new IdentifierManager(0L, 4294967295L); + /** + * Handles the joy of different headers/footers for different pages + */ private XWPFHeaderFooterPolicy headerFooterPolicy; public XWPFDocument(OPCPackage pkg) throws IOException { @@ -125,11 +126,32 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { load(XWPFFactory.getInstance()); } - public XWPFDocument(){ + public XWPFDocument() { super(newPackage()); onDocumentCreate(); } + /** + * Create a new WordProcessingML package and setup the default minimal content + */ + protected static OPCPackage newPackage() { + try { + OPCPackage pkg = OPCPackage.create(new ByteArrayOutputStream()); + // Main part + PackagePartName corePartName = PackagingURIHelper.createPartName(XWPFRelation.DOCUMENT.getDefaultFileName()); + // Create main part relationship + pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT); + // Create main document part + pkg.createPart(corePartName, XWPFRelation.DOCUMENT.getContentType()); + + pkg.getPackageProperties().setCreatorProperty(DOCUMENT_CREATOR); + + return pkg; + } catch (Exception e) { + throw new POIXMLException(e); + } + } + @Override protected void onDocumentRead() throws IOException { try { @@ -152,11 +174,11 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { XWPFTable t = new XWPFTable((CTTbl) o, this); bodyElements.add(t); tables.add(t); - } else if (o instanceof CTSdtBlock){ - XWPFSDT c = new XWPFSDT((CTSdtBlock)o, this); - bodyElements.add(c); - contentControls.add(c); - } + } else if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); + bodyElements.add(c); + contentControls.add(c); + } } cursor.dispose(); @@ -205,7 +227,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { Method onDocumentRead = gp.getClass().getDeclaredMethod("onDocumentRead"); onDocumentRead.setAccessible(true); onDocumentRead.invoke(gp); - } catch(Exception e) { + } catch (Exception e) { throw new POIXMLException(e); } } @@ -217,59 +239,38 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { } } - private void initHyperlinks(){ + private void initHyperlinks() { // Get the hyperlinks // TODO: make me optional/separated in private function try { Iterator relIter = getPackagePart().getRelationshipsByType(XWPFRelation.HYPERLINK.getRelation()).iterator(); - while(relIter.hasNext()) { + while (relIter.hasNext()) { PackageRelationship rel = relIter.next(); hyperlinks.add(new XWPFHyperlink(rel.getId(), rel.getTargetURI().toString())); } - } catch (InvalidFormatException e){ + } catch (InvalidFormatException e) { throw new POIXMLException(e); } } @SuppressWarnings("deprecation") private void initFootnotes() throws XmlException, IOException { - for(POIXMLDocumentPart p : getRelations()){ + for (POIXMLDocumentPart p : getRelations()) { String relation = p.getPackageRelationship().getRelationshipType(); if (relation.equals(XWPFRelation.FOOTNOTE.getRelation())) { - this.footnotes = (XWPFFootnotes)p; + this.footnotes = (XWPFFootnotes) p; this.footnotes.onDocumentRead(); - } else if (relation.equals(XWPFRelation.ENDNOTE.getRelation())){ + } else if (relation.equals(XWPFRelation.ENDNOTE.getRelation())) { EndnotesDocument endnotesDocument = EndnotesDocument.Factory.parse(p.getPackagePart().getInputStream()); - for(CTFtnEdn ctFtnEdn : endnotesDocument.getEndnotes().getEndnoteArray()) { + for (CTFtnEdn ctFtnEdn : endnotesDocument.getEndnotes().getEndnoteArray()) { endnotes.put(ctFtnEdn.getId().intValue(), new XWPFFootnote(this, ctFtnEdn)); } } } } - /** - * Create a new WordProcessingML package and setup the default minimal content - */ - protected static OPCPackage newPackage() { - try { - OPCPackage pkg = OPCPackage.create(new ByteArrayOutputStream()); - // Main part - PackagePartName corePartName = PackagingURIHelper.createPartName(XWPFRelation.DOCUMENT.getDefaultFileName()); - // Create main part relationship - pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT); - // Create main document part - pkg.createPart(corePartName, XWPFRelation.DOCUMENT.getContentType()); - - pkg.getPackageProperties().setCreatorProperty(DOCUMENT_CREATOR); - - return pkg; - } catch (Exception e){ - throw new POIXMLException(e); - } - } - /** * Create a new CTWorkbook with all values set to default */ @@ -278,7 +279,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { ctDocument = CTDocument1.Factory.newInstance(); ctDocument.addNewBody(); - settings = (XWPFSettings) createRelationship(XWPFRelation.SETTINGS,XWPFFactory.getInstance()); + settings = (XWPFSettings) createRelationship(XWPFRelation.SETTINGS, XWPFFactory.getInstance()); POIXMLProperties.ExtendedProperties expProps = getProperties().getExtendedProperties(); expProps.getUnderlyingProperties().setApplication(DOCUMENT_CREATOR); @@ -298,6 +299,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * returns an Iterator with paragraphs and tables + * * @see org.apache.poi.xwpf.usermodel.IBody#getBodyElements() */ @Override @@ -313,7 +315,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphs() */ @Override - public List getParagraphs(){ + public List getParagraphs() { return Collections.unmodifiableList(paragraphs); } @@ -321,7 +323,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * @see org.apache.poi.xwpf.usermodel.IBody#getTables() */ @Override - public List getTables(){ + public List getTables() { return Collections.unmodifiableList(tables); } @@ -330,37 +332,35 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { */ @Override public XWPFTable getTableArray(int pos) { - if (pos > 0 && pos < tables.size()){ + if (pos > 0 && pos < tables.size()) { return tables.get(pos); } return null; } /** - * - * @return the list of footers + * @return the list of footers */ - public List getFooterList(){ + public List getFooterList() { return Collections.unmodifiableList(footers); } - public XWPFFooter getFooterArray(int pos){ + public XWPFFooter getFooterArray(int pos) { return footers.get(pos); } /** - * - * @return the list of headers + * @return the list of headers */ - public List getHeaderList(){ + public List getHeaderList() { return Collections.unmodifiableList(headers); } - public XWPFHeader getHeaderArray(int pos){ + public XWPFHeader getHeaderArray(int pos) { return headers.get(pos); } - public String getTblStyle(XWPFTable table){ + public String getTblStyle(XWPFTable table) { return table.getStyleID(); } @@ -374,17 +374,17 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { } public XWPFFootnote getFootnoteByID(int id) { - if(footnotes == null) return null; + if (footnotes == null) return null; return footnotes.getFootnoteById(id); } public XWPFFootnote getEndnoteByID(int id) { - if(endnotes == null) return null; + if (endnotes == null) return null; return endnotes.get(id); } public List getFootnotes() { - if(footnotes == null) { + if (footnotes == null) { return Collections.emptyList(); } return footnotes.getFootnotesList(); @@ -409,7 +409,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * Get the document part that's defined as the - * given relationship of the core document. + * given relationship of the core document. */ public PackagePart getPartById(String id) { try { @@ -422,7 +422,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * Returns the policy on headers and footers, which - * also provides a way to get at them. + * also provides a way to get at them. */ public XWPFHeaderFooterPolicy getHeaderFooterPolicy() { return headerFooterPolicy; @@ -436,10 +436,10 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { PackagePart[] parts; try { parts = getRelatedByType(XWPFRelation.STYLES.getRelation()); - } catch(InvalidFormatException e) { + } catch (InvalidFormatException e) { throw new IllegalStateException(e); } - if(parts.length != 1) { + if (parts.length != 1) { throw new IllegalStateException("Expecting one Styles document part, but found " + parts.length); } @@ -471,57 +471,56 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * Finds that for example the 2nd entry in the body list is the 1st paragraph */ private int getBodyElementSpecificPos(int pos, List list) { - // If there's nothing to find, skip it - if(list.size() == 0) { - return -1; - } + // If there's nothing to find, skip it + if (list.size() == 0) { + return -1; + } - if(pos >= 0 && pos < bodyElements.size()) { - // Ensure the type is correct - IBodyElement needle = bodyElements.get(pos); - if(needle.getElementType() != list.get(0).getElementType()) { - // Wrong type - return -1; - } + if (pos >= 0 && pos < bodyElements.size()) { + // Ensure the type is correct + IBodyElement needle = bodyElements.get(pos); + if (needle.getElementType() != list.get(0).getElementType()) { + // Wrong type + return -1; + } - // Work back until we find it - int startPos = Math.min(pos, list.size()-1); - for(int i=startPos; i>=0; i--) { - if(list.get(i) == needle) { - return i; - } - } - } + // Work back until we find it + int startPos = Math.min(pos, list.size() - 1); + for (int i = startPos; i >= 0; i--) { + if (list.get(i) == needle) { + return i; + } + } + } - // Couldn't be found - return -1; + // Couldn't be found + return -1; } - + /** * Look up the paragraph at the specified position in the body elements list * and return this paragraphs position in the paragraphs list - * - * @param pos - * The position of the relevant paragraph in the body elements + * + * @param pos The position of the relevant paragraph in the body elements * list * @return the position of the paragraph in the paragraphs list, if there is - * a paragraph at the position in the bodyelements list. Else it - * will return -1 - * + * a paragraph at the position in the bodyelements list. Else it + * will return -1 */ public int getParagraphPos(int pos) { - return getBodyElementSpecificPos(pos, paragraphs); + return getBodyElementSpecificPos(pos, paragraphs); } /** - * get with the position of a table in the bodyelement array list + * get with the position of a table in the bodyelement array list * the position of this table in the table array list + * * @param pos position of the table in the bodyelement array list * @return if there is a table at the position in the bodyelement array list, - * else it will return null. + * else it will return null. */ public int getTablePos(int pos) { - return getBodyElementSpecificPos(pos, tables); + return getBodyElementSpecificPos(pos, tables); } /** @@ -530,10 +529,10 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * of the documents body. When this method is done, the cursor passed as * parameter points to the {@link org.apache.xmlbeans.XmlCursor.TokenType#END} * of the newly inserted paragraph. - * + * * @param cursor * @return the {@link XWPFParagraph} object representing the newly inserted - * CTP object + * CTP object */ @Override public XWPFParagraph insertNewParagraph(XmlCursor cursor) { @@ -635,8 +634,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { cursor.toCursor(tableCursor); cursor.toEndToken(); return newT; - } - finally { + } finally { tableCursor.dispose(); } } @@ -645,6 +643,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * verifies that cursor is on the right position + * * @param cursor */ private boolean isCursorInBody(XmlCursor cursor) { @@ -659,11 +658,11 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { private int getPosOfBodyElement(IBodyElement needle) { BodyElementType type = needle.getElementType(); - IBodyElement current; - for(int i=0; i relations = getRelations(); int i = 1; - for (Iterator it = relations.iterator(); it.hasNext() ; ) { - POIXMLDocumentPart item = it.next(); - if (item.getPackageRelationship().getRelationshipType().equals(relation.getRelation())) { - i++; - } + for (Iterator it = relations.iterator(); it.hasNext(); ) { + POIXMLDocumentPart item = it.next(); + if (item.getPackageRelationship().getRelationshipType().equals(relation.getRelation())) { + i++; + } } return i; } /** * Appends a new paragraph to this document + * * @return a new paragraph */ public XWPFParagraph createParagraph() { @@ -746,16 +749,17 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * Creates an empty numbering if one does not already exist and sets the numbering member + * * @return numbering */ public XWPFNumbering createNumbering() { - if(numbering == null) { + if (numbering == null) { NumberingDocument numberingDoc = NumberingDocument.Factory.newInstance(); XWPFRelation relation = XWPFRelation.NUMBERING; int i = getRelationIndex(relation); - XWPFNumbering wrapper = (XWPFNumbering)createRelationship(relation, XWPFFactory.getInstance(), i); + XWPFNumbering wrapper = (XWPFNumbering) createRelationship(relation, XWPFFactory.getInstance(), i); wrapper.setNumbering(numberingDoc.addNewNumbering()); numbering = wrapper; } @@ -765,61 +769,64 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * Creates an empty styles for the document if one does not already exist + * * @return styles */ public XWPFStyles createStyles() { - if(styles == null) { - StylesDocument stylesDoc = StylesDocument.Factory.newInstance(); + if (styles == null) { + StylesDocument stylesDoc = StylesDocument.Factory.newInstance(); - XWPFRelation relation = XWPFRelation.STYLES; - int i = getRelationIndex(relation); + XWPFRelation relation = XWPFRelation.STYLES; + int i = getRelationIndex(relation); - XWPFStyles wrapper = (XWPFStyles)createRelationship(relation, XWPFFactory.getInstance(), i); - wrapper.setStyles(stylesDoc.addNewStyles()); - styles = wrapper; - } + XWPFStyles wrapper = (XWPFStyles) createRelationship(relation, XWPFFactory.getInstance(), i); + wrapper.setStyles(stylesDoc.addNewStyles()); + styles = wrapper; + } - return styles; + return styles; } /** * Creates an empty footnotes element for the document if one does not already exist + * * @return footnotes */ public XWPFFootnotes createFootnotes() { - if(footnotes == null) { - FootnotesDocument footnotesDoc = FootnotesDocument.Factory.newInstance(); + if (footnotes == null) { + FootnotesDocument footnotesDoc = FootnotesDocument.Factory.newInstance(); - XWPFRelation relation = XWPFRelation.FOOTNOTE; - int i = getRelationIndex(relation); + XWPFRelation relation = XWPFRelation.FOOTNOTE; + int i = getRelationIndex(relation); - XWPFFootnotes wrapper = (XWPFFootnotes)createRelationship(relation, XWPFFactory.getInstance(), i); - wrapper.setFootnotes(footnotesDoc.addNewFootnotes()); - footnotes = wrapper; - } + XWPFFootnotes wrapper = (XWPFFootnotes) createRelationship(relation, XWPFFactory.getInstance(), i); + wrapper.setFootnotes(footnotesDoc.addNewFootnotes()); + footnotes = wrapper; + } - return footnotes; + return footnotes; } public XWPFFootnote addFootnote(CTFtnEdn note) { - return footnotes.addFootnote(note); + return footnotes.addFootnote(note); } public XWPFFootnote addEndnote(CTFtnEdn note) { - XWPFFootnote endnote = new XWPFFootnote(this, note); - endnotes.put(note.getId().intValue(), endnote); - return endnote; + XWPFFootnote endnote = new XWPFFootnote(this, note); + endnotes.put(note.getId().intValue(), endnote); + return endnote; } /** - * remove a BodyElement from bodyElements array list + * remove a BodyElement from bodyElements array list + * * @param pos * @return true if removing was successfully, else return false */ public boolean removeBodyElement(int pos) { if (pos >= 0 && pos < bodyElements.size()) { - BodyElementType type = bodyElements.get(pos).getElementType(); - if (type == BodyElementType.TABLE){ + BodyElementType type = bodyElements.get(pos).getElementType(); + if (type == BodyElementType.TABLE) { int tablePos = getTablePos(pos); tables.remove(tablePos); ctDocument.getBody().removeTbl(tablePos); @@ -830,13 +837,14 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { ctDocument.getBody().removeP(paraPos); } bodyElements.remove(pos); - return true; + return true; } return false; } /** * copies content of a paragraph to a existing paragraph in the list paragraphs at position pos + * * @param paragraph * @param pos */ @@ -859,6 +867,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * Create an empty table with one row and one column as default. + * * @return a new table */ public XWPFTable createTable() { @@ -870,19 +879,20 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * Create an empty table with a number of rows and cols specified + * * @param rows * @param cols * @return table */ public XWPFTable createTable(int rows, int cols) { - XWPFTable table = new XWPFTable(ctDocument.getBody().addNewTbl(), this, rows, cols); - bodyElements.add(table); - tables.add(table); - return table; + XWPFTable table = new XWPFTable(ctDocument.getBody().addNewTbl(), this, rows, cols); + bodyElements.add(table); + tables.add(table); + return table; } /** - * + * */ public void createTOC() { CTSdtBlock block = this.getDocument().getBody().addNewSdt(); @@ -900,7 +910,9 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { } } - /**Replace content of table in array tables at position pos with a + /** + * Replace content of table in array tables at position pos with a + * * @param pos * @param table */ @@ -919,7 +931,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * <w:settings ... > * <w:documentProtection w:edit="readOnly" w:enforcement="1"/> * - * + * * @return true if documentProtection is enforced with option readOnly */ public boolean isEnforcedReadonlyProtection() { @@ -936,7 +948,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * <w:settings ... > * <w:documentProtection w:edit="forms" w:enforcement="1"/> * - * + * * @return true if documentProtection is enforced with option forms */ public boolean isEnforcedFillingFormsProtection() { @@ -953,7 +965,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * <w:settings ... > * <w:documentProtection w:edit="comments" w:enforcement="1"/> * - * + * * @return true if documentProtection is enforced with option comments */ public boolean isEnforcedCommentsProtection() { @@ -970,7 +982,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * <w:settings ... > * <w:documentProtection w:edit="trackedChanges" w:enforcement="1"/> * - * + * * @return true if documentProtection is enforced with option trackedChanges */ public boolean isEnforcedTrackedChangesProtection() { @@ -1002,21 +1014,21 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { *
    * sample snippet from settings.xml *
    -     *   <w:documentProtection w:edit="readOnly" w:enforcement="1" 
    +     *   <w:documentProtection w:edit="readOnly" w:enforcement="1"
          *       w:cryptProviderType="rsaAES" w:cryptAlgorithmClass="hash"
          *       w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="14"
          *       w:cryptSpinCount="100000" w:hash="..." w:salt="...."
          *   />
          * 
    - * + * * @param password the plaintext password, if null no password will be applied * @param hashAlgo the hash algorithm - only md2, m5, sha1, sha256, sha384 and sha512 are supported. - * if null, it will default default to sha1 + * if null, it will default default to sha1 */ public void enforceReadonlyProtection(String password, HashAlgorithm hashAlgo) { settings.setEnforcementEditValue(STDocProtect.READ_ONLY, password, hashAlgo); } - + /** * Enforce the Filling Forms protection.
    * In the documentProtection tag inside settings.xml file,
    @@ -1038,21 +1050,21 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { *
    * sample snippet from settings.xml *
    -     *   <w:documentProtection w:edit="forms" w:enforcement="1" 
    +     *   <w:documentProtection w:edit="forms" w:enforcement="1"
          *       w:cryptProviderType="rsaAES" w:cryptAlgorithmClass="hash"
          *       w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="14"
          *       w:cryptSpinCount="100000" w:hash="..." w:salt="...."
          *   />
          * 
    - * + * * @param password the plaintext password, if null no password will be applied * @param hashAlgo the hash algorithm - only md2, m5, sha1, sha256, sha384 and sha512 are supported. - * if null, it will default default to sha1 + * if null, it will default default to sha1 */ public void enforceFillingFormsProtection(String password, HashAlgorithm hashAlgo) { settings.setEnforcementEditValue(STDocProtect.FORMS, password, hashAlgo); } - + /** * Enforce the Comments protection.
    * In the documentProtection tag inside settings.xml file,
    @@ -1074,21 +1086,21 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { *
    * sample snippet from settings.xml *
    -     *   <w:documentProtection w:edit="comments" w:enforcement="1" 
    +     *   <w:documentProtection w:edit="comments" w:enforcement="1"
          *       w:cryptProviderType="rsaAES" w:cryptAlgorithmClass="hash"
          *       w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="14"
          *       w:cryptSpinCount="100000" w:hash="..." w:salt="...."
          *   />
          * 
    - * + * * @param password the plaintext password, if null no password will be applied * @param hashAlgo the hash algorithm - only md2, m5, sha1, sha256, sha384 and sha512 are supported. - * if null, it will default default to sha1 + * if null, it will default default to sha1 */ public void enforceCommentsProtection(String password, HashAlgorithm hashAlgo) { settings.setEnforcementEditValue(STDocProtect.COMMENTS, password, hashAlgo); } - + /** * Enforce the Tracked Changes protection.
    * In the documentProtection tag inside settings.xml file,
    @@ -1110,16 +1122,16 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { *
    * sample snippet from settings.xml *
    -     *   <w:documentProtection w:edit="trackedChanges" w:enforcement="1" 
    +     *   <w:documentProtection w:edit="trackedChanges" w:enforcement="1"
          *       w:cryptProviderType="rsaAES" w:cryptAlgorithmClass="hash"
          *       w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="14"
          *       w:cryptSpinCount="100000" w:hash="..." w:salt="...."
          *   />
          * 
    - * + * * @param password the plaintext password, if null no password will be applied * @param hashAlgo the hash algorithm - only md2, m5, sha1, sha256, sha384 and sha512 are supported. - * if null, it will default default to sha1 + * if null, it will default default to sha1 */ public void enforceTrackedChangesProtection(String password, HashAlgorithm hashAlgo) { settings.setEnforcementEditValue(STDocProtect.TRACKED_CHANGES, password, hashAlgo); @@ -1134,7 +1146,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { public boolean validateProtectionPassword(String password) { return settings.validateProtectionPassword(password); } - + /** * Remove protection enforcement.
    * In the documentProtection tag inside settings.xml file
    @@ -1148,38 +1160,39 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * Enforces fields update on document open (in Word). * In the settings.xml file
    * sets the updateSettings value to true (w:updateSettings w:val="true") - * - * NOTICES: - *
      - *
    • Causing Word to ask on open: "This document contains fields that may refer to other files. Do you want to update the fields in this document?" - * (if "Update automatic links at open" is enabled)
    • - *
    • Flag is removed after saving with changes in Word
    • - *
    + *

    + * NOTICES: + *

      + *
    • Causing Word to ask on open: "This document contains fields that may refer to other files. Do you want to update the fields in this document?" + * (if "Update automatic links at open" is enabled)
    • + *
    • Flag is removed after saving with changes in Word
    • + *
    */ public void enforceUpdateFields() { settings.setUpdateFields(); } - + /** - * Check if revision tracking is turned on. - * - * @return true if revision tracking is turned on - */ - public boolean isTrackRevisions() { - return settings.isTrackRevisions(); - } - - /** - * Enable or disable revision tracking. - * - * @param enable true to turn on revision tracking, false to turn off revision tracking - */ - public void setTrackRevisions(boolean enable) { - settings.setTrackRevisions(enable); - } + * Check if revision tracking is turned on. + * + * @return true if revision tracking is turned on + */ + public boolean isTrackRevisions() { + return settings.isTrackRevisions(); + } + + /** + * Enable or disable revision tracking. + * + * @param enable true to turn on revision tracking, false to turn off revision tracking + */ + public void setTrackRevisions(boolean enable) { + settings.setTrackRevisions(enable); + } /** * inserts an existing XWPFTable to the arrays bodyElements and tables + * * @param pos * @param table */ @@ -1199,6 +1212,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * Returns all Pictures, which are referenced from the document itself. + * * @return a {@link List} of {@link XWPFPictureData}. The returned {@link List} is unmodifiable. Use #a */ public List getAllPictures() { @@ -1223,14 +1237,12 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { list = new ArrayList(1); packagePictures.put(picData.getChecksum(), list); } - if (!list.contains(picData)) - { + if (!list.contains(picData)) { list.add(picData); } } - - XWPFPictureData findPackagePictureData(byte[] pictureData, int format) - { + + XWPFPictureData findPackagePictureData(byte[] pictureData, int format) { long checksum = IOUtils.calculateChecksum(pictureData); XWPFPictureData xwpfPicData = null; /* @@ -1246,20 +1258,18 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { xwpfPicData = curElem; } } - } + } return xwpfPicData; } - public String addPictureData(byte[] pictureData,int format) throws InvalidFormatException - { + public String addPictureData(byte[] pictureData, int format) throws InvalidFormatException { XWPFPictureData xwpfPicData = findPackagePictureData(pictureData, format); POIXMLRelation relDesc = XWPFPictureData.RELATIONS[format]; - - if (xwpfPicData == null) - { + + if (xwpfPicData == null) { /* Part doesn't exist, create a new one */ int idx = getNextPicNameNumber(format); - xwpfPicData = (XWPFPictureData) createRelationship(relDesc, XWPFFactory.getInstance(),idx); + xwpfPicData = (XWPFPictureData) createRelationship(relDesc, XWPFFactory.getInstance(), idx); /* write bytes to new part */ PackagePart picDataPart = xwpfPicData.getPackagePart(); OutputStream out = null; @@ -1278,11 +1288,9 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { registerPackagePictureData(xwpfPicData); pictures.add(xwpfPicData); - + return getRelationId(xwpfPicData); - } - else if (!getRelations().contains(xwpfPicData)) - { + } else if (!getRelations().contains(xwpfPicData)) { /* * Part already existed, but was not related so far. Create * relationship to the already existing part and update @@ -1293,21 +1301,18 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { TargetMode targetMode = TargetMode.INTERNAL; PackagePartName partName = picDataPart.getPartName(); String relation = relDesc.getRelation(); - PackageRelationship relShip = getPackagePart().addRelationship(partName,targetMode,relation); + PackageRelationship relShip = getPackagePart().addRelationship(partName, targetMode, relation); String id = relShip.getId(); - addRelation(id,xwpfPicData); + addRelation(id, xwpfPicData); pictures.add(xwpfPicData); return id; - } - else - { + } else { /* Part already existed, get relation id and return it */ return getRelationId(xwpfPicData); } } - - public String addPictureData(InputStream is,int format) throws InvalidFormatException - { + + public String addPictureData(InputStream is, int format) throws InvalidFormatException { try { byte[] data = IOUtils.toByteArray(is); return addPictureData(data, format); @@ -1318,9 +1323,10 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * get the next free ImageNumber + * * @param format * @return the next free ImageNumber - * @throws InvalidFormatException + * @throws InvalidFormatException */ public int getNextPicNameNumber(int format) throws InvalidFormatException { int img = getAllPackagePictures().size() + 1; @@ -1336,6 +1342,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * returns the PictureData by blipID + * * @param blipID * @return XWPFPictureData of a specificID */ @@ -1350,6 +1357,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * getNumbering + * * @return numbering */ public XWPFNumbering getNumbering() { @@ -1358,6 +1366,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * get Styles + * * @return styles for this document */ public XWPFStyles getStyles() { @@ -1366,7 +1375,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * get the paragraph with the CTP class p - * + * * @param p * @return the paragraph with the CTP class p */ @@ -1382,9 +1391,10 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * get a table by its CTTbl-Object + * * @param ctTbl - * @see org.apache.poi.xwpf.usermodel.IBody#getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) * @return a table by its CTTbl-Object or null + * @see org.apache.poi.xwpf.usermodel.IBody#getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) */ @Override public XWPFTable getTable(CTTbl ctTbl) { @@ -1406,6 +1416,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * Returns the paragraph that of position pos + * * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int) */ @Override @@ -1420,6 +1431,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { * returns the Part, to which the body belongs, which you need for adding relationship to other parts * Actually it is needed of the class XWPFTableCell. Because you have to know to which part the tableCell * belongs. + * * @see org.apache.poi.xwpf.usermodel.IBody#getPart() */ @Override @@ -1441,6 +1453,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { /** * get the TableCell which belongs to the TableCell + * * @param cell */ @Override @@ -1448,19 +1461,19 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody { XmlCursor cursor = cell.newCursor(); cursor.toParent(); XmlObject o = cursor.getObject(); - if(!(o instanceof CTRow)){ + if (!(o instanceof CTRow)) { return null; } - CTRow row = (CTRow)o; + CTRow row = (CTRow) o; cursor.toParent(); o = cursor.getObject(); cursor.dispose(); - if(! (o instanceof CTTbl)){ + if (!(o instanceof CTTbl)) { return null; } CTTbl tbl = (CTTbl) o; XWPFTable table = getTable(tbl); - if(table == null){ + if (table == null) { return null; } XWPFTableRow tableRow = table.getRow(row); diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFactory.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFactory.java index c6b2c2d3e..4fb02ce9b 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFactory.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFactory.java @@ -28,30 +28,29 @@ import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; -/** - * @author Yegor Kozlov - */ -public final class XWPFFactory extends POIXMLFactory { - - private static final POILogger logger = POILogFactory.getLogger(XWPFFactory.class); - - private XWPFFactory(){ - - } - - private static final XWPFFactory inst = new XWPFFactory(); - - public static XWPFFactory getInstance(){ - return inst; - } - - @Override - public POIXMLDocumentPart createDocumentPart(POIXMLDocumentPart parent, PackageRelationship rel, PackagePart part){ - POIXMLRelation descriptor = XWPFRelation.getInstance(rel.getRelationshipType()); - if(descriptor == null || descriptor.getRelationClass() == null){ - logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType()); - return new POIXMLDocumentPart(part, rel); - } +/** + * @author Yegor Kozlov + */ +public final class XWPFFactory extends POIXMLFactory { + + private static final POILogger logger = POILogFactory.getLogger(XWPFFactory.class); + private static final XWPFFactory inst = new XWPFFactory(); + + private XWPFFactory() { + + } + + public static XWPFFactory getInstance() { + return inst; + } + + @Override + public POIXMLDocumentPart createDocumentPart(POIXMLDocumentPart parent, PackageRelationship rel, PackagePart part) { + POIXMLRelation descriptor = XWPFRelation.getInstance(rel.getRelationshipType()); + if (descriptor == null || descriptor.getRelationClass() == null) { + logger.log(POILogger.DEBUG, "using default POIXMLDocumentPart for " + rel.getRelationshipType()); + return new POIXMLDocumentPart(part, rel); + } try { Class cls = descriptor.getRelationClass(); @@ -59,23 +58,23 @@ public final class XWPFFactory extends POIXMLFactory { Constructor constructor = cls.getDeclaredConstructor(POIXMLDocumentPart.class, PackagePart.class, PackageRelationship.class); return constructor.newInstance(parent, part, rel); } catch (NoSuchMethodException e) { - Constructor constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class); - return constructor.newInstance(part, rel); - } - } catch (Exception e){ - throw new POIXMLException(e); - } - } - - @Override - public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor){ - try { - Class cls = descriptor.getRelationClass(); - Constructor constructor = cls.getDeclaredConstructor(); - return constructor.newInstance(); - } catch (Exception e){ - throw new POIXMLException(e); - } - } + Constructor constructor = cls.getDeclaredConstructor(PackagePart.class, PackageRelationship.class); + return constructor.newInstance(part, rel); + } + } catch (Exception e) { + throw new POIXMLException(e); + } + } + + @Override + public POIXMLDocumentPart newDocumentPart(POIXMLRelation descriptor) { + try { + Class cls = descriptor.getRelationClass(); + Constructor constructor = cls.getDeclaredConstructor(); + return constructor.newInstance(); + } catch (Exception e) { + throw new POIXMLException(e); + } + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java index 8485f1d6c..8ae33260f 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFooter.java @@ -53,16 +53,16 @@ public class XWPFFooter extends XWPFHeaderFooter { while (cursor.toNextSelection()) { XmlObject o = cursor.getObject(); if (o instanceof CTP) { - XWPFParagraph p = new XWPFParagraph((CTP)o, this); + XWPFParagraph p = new XWPFParagraph((CTP) o, this); paragraphs.add(p); bodyElements.add(p); } if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl)o, this); + XWPFTable t = new XWPFTable((CTTbl) o, this); tables.add(t); bodyElements.add(t); } - + } cursor.dispose(); } @@ -78,7 +78,7 @@ public class XWPFFooter extends XWPFHeaderFooter { protected void commit() throws IOException { XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "ftr")); - Map map = new HashMap(); + Map map = new HashMap(); map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve"); map.put("urn:schemas-microsoft-com:office:office", "o"); map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); @@ -95,8 +95,8 @@ public class XWPFFooter extends XWPFHeaderFooter { out.close(); } - @Override - protected void onDocumentRead() throws IOException{ + @Override + protected void onDocumentRead() throws IOException { super.onDocumentRead(); FtrDocument ftrDocument = null; InputStream is; @@ -111,19 +111,19 @@ public class XWPFFooter extends XWPFHeaderFooter { while (cursor.toNextSelection()) { XmlObject o = cursor.getObject(); if (o instanceof CTP) { - XWPFParagraph p = new XWPFParagraph((CTP)o, this); + XWPFParagraph p = new XWPFParagraph((CTP) o, this); paragraphs.add(p); bodyElements.add(p); } if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl)o, this); + XWPFTable t = new XWPFTable((CTTbl) o, this); tables.add(t); bodyElements.add(t); } - if (o instanceof CTSdtBlock){ - XWPFSDT c = new XWPFSDT((CTSdtBlock)o, this); - bodyElements.add(c); - } + if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); + bodyElements.add(c); + } } cursor.dispose(); } catch (Exception e) { @@ -133,6 +133,7 @@ public class XWPFFooter extends XWPFHeaderFooter { /** * get the PartType of the body + * * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() */ public BodyType getPartType() { diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnote.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnote.java index 5f0367d6b..7b51ed454 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnote.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnote.java @@ -27,64 +27,64 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; - -public class XWPFFootnote implements Iterable,IBody { - private List paragraphs = new ArrayList(); - private List tables= new ArrayList(); - private List pictures = new ArrayList(); - private List bodyElements = new ArrayList(); - +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; + +public class XWPFFootnote implements Iterable, IBody { + private List paragraphs = new ArrayList(); + private List tables = new ArrayList(); + private List pictures = new ArrayList(); + private List bodyElements = new ArrayList(); + private CTFtnEdn ctFtnEdn; private XWPFFootnotes footnotes; - private XWPFDocument document; - - public XWPFFootnote(CTFtnEdn note, XWPFFootnotes xFootnotes) { - footnotes = xFootnotes; - ctFtnEdn = note; - document = xFootnotes.getXWPFDocument(); - init(); - } - - public XWPFFootnote(XWPFDocument document, CTFtnEdn body) { - ctFtnEdn = body; - this.document = document; - init(); - } - - private void init(){ - XmlCursor cursor = ctFtnEdn.newCursor(); - //copied from XWPFDocument...should centralize this code - //to avoid duplication - cursor.selectPath("./*"); - while (cursor.toNextSelection()) { - XmlObject o = cursor.getObject(); - if (o instanceof CTP) { - XWPFParagraph p = new XWPFParagraph((CTP) o, this); - bodyElements.add(p); - paragraphs.add(p); - } else if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl) o, this); - bodyElements.add(t); - tables.add(t); - } else if (o instanceof CTSdtBlock){ - XWPFSDT c = new XWPFSDT((CTSdtBlock)o, this); - bodyElements.add(c); - } - - } - cursor.dispose(); - } - - public List getParagraphs() { - return paragraphs; - } - - public Iterator iterator(){ - return paragraphs.iterator(); - } - + private XWPFDocument document; + + public XWPFFootnote(CTFtnEdn note, XWPFFootnotes xFootnotes) { + footnotes = xFootnotes; + ctFtnEdn = note; + document = xFootnotes.getXWPFDocument(); + init(); + } + + public XWPFFootnote(XWPFDocument document, CTFtnEdn body) { + ctFtnEdn = body; + this.document = document; + init(); + } + + private void init() { + XmlCursor cursor = ctFtnEdn.newCursor(); + //copied from XWPFDocument...should centralize this code + //to avoid duplication + cursor.selectPath("./*"); + while (cursor.toNextSelection()) { + XmlObject o = cursor.getObject(); + if (o instanceof CTP) { + XWPFParagraph p = new XWPFParagraph((CTP) o, this); + bodyElements.add(p); + paragraphs.add(p); + } else if (o instanceof CTTbl) { + XWPFTable t = new XWPFTable((CTTbl) o, this); + bodyElements.add(t); + tables.add(t); + } else if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); + bodyElements.add(c); + } + + } + cursor.dispose(); + } + + public List getParagraphs() { + return paragraphs; + } + + public Iterator iterator() { + return paragraphs.iterator(); + } + public List getTables() { return tables; } @@ -95,226 +95,231 @@ public class XWPFFootnote implements Iterable,IBody { public List getBodyElements() { return bodyElements; - } - - public CTFtnEdn getCTFtnEdn() { - return ctFtnEdn; - } - - public void setCTFtnEdn(CTFtnEdn footnote) { - ctFtnEdn = footnote; - } - - /** + } + + public CTFtnEdn getCTFtnEdn() { + return ctFtnEdn; + } + + public void setCTFtnEdn(CTFtnEdn footnote) { + ctFtnEdn = footnote; + } + + /** * @param pos in table array * @return The table at position pos - * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int) - */ - public XWPFTable getTableArray(int pos) { - if(pos > 0 && pos < tables.size()){ - return tables.get(pos); - } - return null; + * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int) + */ + public XWPFTable getTableArray(int pos) { + if (pos > 0 && pos < tables.size()) { + return tables.get(pos); + } + return null; } - - /** - * inserts an existing XWPFTable to the arrays bodyElements and tables - * @param pos - * @param table - * @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int pos, XWPFTable table) + + /** + * inserts an existing XWPFTable to the arrays bodyElements and tables + * + * @param pos + * @param table + * @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int pos, XWPFTable table) */ @SuppressWarnings("deprecation") public void insertTable(int pos, XWPFTable table) { - bodyElements.add(pos, table); - int i = 0; - for (CTTbl tbl : ctFtnEdn.getTblArray()) { - if(tbl == table.getCTTbl()){ - break; - } - i++; + bodyElements.add(pos, table); + int i = 0; + for (CTTbl tbl : ctFtnEdn.getTblArray()) { + if (tbl == table.getCTTbl()) { + break; + } + i++; } tables.add(i, table); } - /** - * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header - * the method will return this table - * if there is no corresponding {@link XWPFTable} the method will return null - * @param ctTable - * @see org.apache.poi.xwpf.usermodel.IBody#getTable(CTTbl ctTable) - */ - public XWPFTable getTable(CTTbl ctTable){ - for (XWPFTable table : tables) { - if(table==null) - return null; - if(table.getCTTbl().equals(ctTable)) - return table; - } - return null; + /** + * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header + * the method will return this table + * if there is no corresponding {@link XWPFTable} the method will return null + * + * @param ctTable + * @see org.apache.poi.xwpf.usermodel.IBody#getTable(CTTbl ctTable) + */ + public XWPFTable getTable(CTTbl ctTable) { + for (XWPFTable table : tables) { + if (table == null) + return null; + if (table.getCTTbl().equals(ctTable)) + return table; + } + return null; } - /** - * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer - * the method will return this paragraph - * if there is no corresponding {@link XWPFParagraph} the method will return null - * @param p is instance of CTP and is searching for an XWPFParagraph - * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer - * XWPFParagraph with the correspondig CTP p - * @see org.apache.poi.xwpf.usermodel.IBody#getParagraph(CTP p) - */ - public XWPFParagraph getParagraph(CTP p){ - for (XWPFParagraph paragraph : paragraphs) { - if(paragraph.getCTP().equals(p)) - return paragraph; - } - return null; + /** + * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer + * the method will return this paragraph + * if there is no corresponding {@link XWPFParagraph} the method will return null + * + * @param p is instance of CTP and is searching for an XWPFParagraph + * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer + * XWPFParagraph with the correspondig CTP p + * @see org.apache.poi.xwpf.usermodel.IBody#getParagraph(CTP p) + */ + public XWPFParagraph getParagraph(CTP p) { + for (XWPFParagraph paragraph : paragraphs) { + if (paragraph.getCTP().equals(p)) + return paragraph; + } + return null; } - - /** - * Returns the paragraph that holds - * the text of the header or footer. - * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int pos) - */ - public XWPFParagraph getParagraphArray(int pos) { + + /** + * Returns the paragraph that holds + * the text of the header or footer. + * + * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int pos) + */ + public XWPFParagraph getParagraphArray(int pos) { return paragraphs.get(pos); } - - /** - * get the TableCell which belongs to the TableCell - * @param cell - * @see org.apache.poi.xwpf.usermodel.IBody#getTableCell(CTTc cell) - */ + + /** + * get the TableCell which belongs to the TableCell + * + * @param cell + * @see org.apache.poi.xwpf.usermodel.IBody#getTableCell(CTTc cell) + */ public XWPFTableCell getTableCell(CTTc cell) { - XmlCursor cursor = cell.newCursor(); - cursor.toParent(); - XmlObject o = cursor.getObject(); - if(!(o instanceof CTRow)){ - return null; - } - CTRow row = (CTRow)o; - cursor.toParent(); - o = cursor.getObject(); - cursor.dispose(); - if(! (o instanceof CTTbl)){ - return null; - } - CTTbl tbl = (CTTbl) o; - XWPFTable table = getTable(tbl); - if(table == null){ - return null; - } - XWPFTableRow tableRow = table.getRow(row); - if(row == null){ - return null; - } - return tableRow.getTableCell(cell); + XmlCursor cursor = cell.newCursor(); + cursor.toParent(); + XmlObject o = cursor.getObject(); + if (!(o instanceof CTRow)) { + return null; + } + CTRow row = (CTRow) o; + cursor.toParent(); + o = cursor.getObject(); + cursor.dispose(); + if (!(o instanceof CTTbl)) { + return null; + } + CTTbl tbl = (CTTbl) o; + XWPFTable table = getTable(tbl); + if (table == null) { + return null; + } + XWPFTableRow tableRow = table.getRow(row); + if (row == null) { + return null; + } + return tableRow.getTableCell(cell); } - - /** - * verifies that cursor is on the right position - * @param cursor - */ - private boolean isCursorInFtn(XmlCursor cursor) { - XmlCursor verify = cursor.newCursor(); - verify.toParent(); - if(verify.getObject() == this.ctFtnEdn){ - return true; - } - return false; - } - - public POIXMLDocumentPart getOwner(){ - return footnotes; - } - - /** - * - * @param cursor - * @return the inserted table - * @see org.apache.poi.xwpf.usermodel.IBody#insertNewTbl(XmlCursor cursor) - */ - public XWPFTable insertNewTbl(XmlCursor cursor) { - if(isCursorInFtn(cursor)){ - String uri = CTTbl.type.getName().getNamespaceURI(); - String localPart = "tbl"; - cursor.beginElement(localPart,uri); - cursor.toParent(); - CTTbl t = (CTTbl)cursor.getObject(); - XWPFTable newT = new XWPFTable(t, this); - cursor.removeXmlContents(); - XmlObject o = null; - while(!(o instanceof CTTbl)&&(cursor.toPrevSibling())){ - o = cursor.getObject(); - } - if(!(o instanceof CTTbl)){ - tables.add(0, newT); - } - else{ - int pos = tables.indexOf(getTable((CTTbl)o))+1; - tables.add(pos,newT); - } - int i=0; - cursor = t.newCursor(); - while(cursor.toPrevSibling()){ - o =cursor.getObject(); - if(o instanceof CTP || o instanceof CTTbl) - i++; - } - bodyElements.add(i, newT); + + /** + * verifies that cursor is on the right position + * + * @param cursor + */ + private boolean isCursorInFtn(XmlCursor cursor) { + XmlCursor verify = cursor.newCursor(); + verify.toParent(); + if (verify.getObject() == this.ctFtnEdn) { + return true; + } + return false; + } + + public POIXMLDocumentPart getOwner() { + return footnotes; + } + + /** + * @param cursor + * @return the inserted table + * @see org.apache.poi.xwpf.usermodel.IBody#insertNewTbl(XmlCursor cursor) + */ + public XWPFTable insertNewTbl(XmlCursor cursor) { + if (isCursorInFtn(cursor)) { + String uri = CTTbl.type.getName().getNamespaceURI(); + String localPart = "tbl"; + cursor.beginElement(localPart, uri); + cursor.toParent(); + CTTbl t = (CTTbl) cursor.getObject(); + XWPFTable newT = new XWPFTable(t, this); + cursor.removeXmlContents(); + XmlObject o = null; + while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) { + o = cursor.getObject(); + } + if (!(o instanceof CTTbl)) { + tables.add(0, newT); + } else { + int pos = tables.indexOf(getTable((CTTbl) o)) + 1; + tables.add(pos, newT); + } + int i = 0; + cursor = t.newCursor(); + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) + i++; + } + bodyElements.add(i, newT); cursor = t.newCursor(); cursor.toEndToken(); return newT; } return null; } - - /** - * add a new paragraph at position of the cursor - * @param cursor - * @return the inserted paragraph - * @see org.apache.poi.xwpf.usermodel.IBody#insertNewParagraph(XmlCursor cursor) - */ - public XWPFParagraph insertNewParagraph(XmlCursor cursor){ - if(isCursorInFtn(cursor)){ - String uri = CTP.type.getName().getNamespaceURI(); - String localPart = "p"; - cursor.beginElement(localPart,uri); - cursor.toParent(); - CTP p = (CTP)cursor.getObject(); - XWPFParagraph newP = new XWPFParagraph(p, this); - XmlObject o = null; - while(!(o instanceof CTP)&&(cursor.toPrevSibling())){ - o = cursor.getObject(); - } - if((!(o instanceof CTP)) || (CTP)o == p){ - paragraphs.add(0, newP); - } - else{ - int pos = paragraphs.indexOf(getParagraph((CTP)o))+1; - paragraphs.add(pos,newP); - } - int i=0; - cursor.toCursor(p.newCursor()); - while(cursor.toPrevSibling()){ - o =cursor.getObject(); - if(o instanceof CTP || o instanceof CTTbl) - i++; - } - bodyElements.add(i, newP); + + /** + * add a new paragraph at position of the cursor + * + * @param cursor + * @return the inserted paragraph + * @see org.apache.poi.xwpf.usermodel.IBody#insertNewParagraph(XmlCursor cursor) + */ + public XWPFParagraph insertNewParagraph(XmlCursor cursor) { + if (isCursorInFtn(cursor)) { + String uri = CTP.type.getName().getNamespaceURI(); + String localPart = "p"; + cursor.beginElement(localPart, uri); + cursor.toParent(); + CTP p = (CTP) cursor.getObject(); + XWPFParagraph newP = new XWPFParagraph(p, this); + XmlObject o = null; + while (!(o instanceof CTP) && (cursor.toPrevSibling())) { + o = cursor.getObject(); + } + if ((!(o instanceof CTP)) || (CTP) o == p) { + paragraphs.add(0, newP); + } else { + int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1; + paragraphs.add(pos, newP); + } + int i = 0; + cursor.toCursor(p.newCursor()); + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) + i++; + } + bodyElements.add(i, newP); cursor.toCursor(p.newCursor()); cursor.toEndToken(); return newP; } return null; } - - /** - * add a new table to the end of the footnote - * @param table - * @return the added XWPFTable - */ + + /** + * add a new table to the end of the footnote + * + * @param table + * @return the added XWPFTable + */ public XWPFTable addNewTbl(CTTbl table) { CTTbl newTable = ctFtnEdn.addNewTbl(); newTable.set(table); @@ -322,12 +327,13 @@ public class XWPFFootnote implements Iterable,IBody { tables.add(xTable); return xTable; } - - /** - * add a new paragraph to the end of the footnote - * @param paragraph - * @return the added XWPFParagraph - */ + + /** + * add a new paragraph to the end of the footnote + * + * @param paragraph + * @return the added XWPFParagraph + */ public XWPFParagraph addNewParagraph(CTP paragraph) { CTP newPara = ctFtnEdn.addNewP(); newPara.set(paragraph); @@ -336,26 +342,28 @@ public class XWPFFootnote implements Iterable,IBody { return xPara; } - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getXWPFDocument() - */ - public XWPFDocument getXWPFDocument() { - return document; - } - - /** - * returns the Part, to which the body belongs, which you need for adding relationship to other parts - * @see org.apache.poi.xwpf.usermodel.IBody#getPart() - */ - public POIXMLDocumentPart getPart() { + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getXWPFDocument() + */ + public XWPFDocument getXWPFDocument() { + return document; + } + + /** + * returns the Part, to which the body belongs, which you need for adding relationship to other parts + * + * @see org.apache.poi.xwpf.usermodel.IBody#getPart() + */ + public POIXMLDocumentPart getPart() { return footnotes; } - - /** - * get the PartType of the body - * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() - */ - public BodyType getPartType() { + + /** + * get the PartType of the body + * + * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() + */ + public BodyType getPartType() { return BodyType.FOOTNOTE; } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java index 8647454f2..c84cab66c 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java @@ -31,32 +31,31 @@ import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFootnotes; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.FootnotesDocument; - -/** - * Looks after the collection of Footnotes for a document - */ -public class XWPFFootnotes extends POIXMLDocumentPart { - private List listFootnote = new ArrayList(); - private CTFootnotes ctFootnotes; - - protected XWPFDocument document; - - /** - * Construct XWPFFootnotes from a package part - * - * @param part the package part holding the data of the footnotes, - * @param rel the package relationship of type "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" - */ - public XWPFFootnotes(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException{ - super(part, rel); - } - +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlOptions; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFootnotes; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.FootnotesDocument; + +/** + * Looks after the collection of Footnotes for a document + */ +public class XWPFFootnotes extends POIXMLDocumentPart { + protected XWPFDocument document; + private List listFootnote = new ArrayList(); + private CTFootnotes ctFootnotes; + + /** + * Construct XWPFFootnotes from a package part + * + * @param part the package part holding the data of the footnotes, + * @param rel the package relationship of type "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" + */ + public XWPFFootnotes(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException { + super(part, rel); + } + /** * Construct XWPFFootnotes from scratch for a new document. */ @@ -65,33 +64,33 @@ public class XWPFFootnotes extends POIXMLDocumentPart { /** * Read document - */ - @Override - @SuppressWarnings("deprecation") - protected void onDocumentRead () throws IOException { - FootnotesDocument notesDoc; - try { - InputStream is = getPackagePart().getInputStream(); + */ + @Override + @SuppressWarnings("deprecation") + protected void onDocumentRead() throws IOException { + FootnotesDocument notesDoc; + try { + InputStream is = getPackagePart().getInputStream(); notesDoc = FootnotesDocument.Factory.parse(is); ctFootnotes = notesDoc.getFootnotes(); } catch (XmlException e) { throw new POIXMLException(); - } - - // Find our footnotes - for(CTFtnEdn note : ctFootnotes.getFootnoteArray()) { - listFootnote.add(new XWPFFootnote(note, this)); - } - } + } + + // Find our footnotes + for (CTFtnEdn note : ctFootnotes.getFootnoteArray()) { + listFootnote.add(new XWPFFootnote(note, this)); + } + } @Override - protected void commit() throws IOException { - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTFootnotes.type.getName().getNamespaceURI(), "footnotes")); - Map map = new HashMap(); - map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); - map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w"); - xmlOptions.setSaveSuggestedPrefixes(map); + protected void commit() throws IOException { + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + xmlOptions.setSaveSyntheticDocumentElement(new QName(CTFootnotes.type.getName().getNamespaceURI(), "footnotes")); + Map map = new HashMap(); + map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); + map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w"); + xmlOptions.setSaveSuggestedPrefixes(map); PackagePart part = getPackagePart(); OutputStream out = part.getOutputStream(); ctFootnotes.save(out, xmlOptions); @@ -100,59 +99,62 @@ public class XWPFFootnotes extends POIXMLDocumentPart { public List getFootnotesList() { return listFootnote; + } + + public XWPFFootnote getFootnoteById(int id) { + for (XWPFFootnote note : listFootnote) { + if (note.getCTFtnEdn().getId().intValue() == id) + return note; + } + return null; } - - public XWPFFootnote getFootnoteById(int id) { - for(XWPFFootnote note : listFootnote) { - if(note.getCTFtnEdn().getId().intValue() == id) - return note; - } - return null; - } - - /** - * Sets the ctFootnotes - * @param footnotes - */ - public void setFootnotes(CTFootnotes footnotes) { + + /** + * Sets the ctFootnotes + * + * @param footnotes + */ + public void setFootnotes(CTFootnotes footnotes) { ctFootnotes = footnotes; } - - /** - * add an XWPFFootnote to the document - * @param footnote - * @throws IOException - */ - public void addFootnote(XWPFFootnote footnote){ - listFootnote.add(footnote); - ctFootnotes.addNewFootnote().set(footnote.getCTFtnEdn()); - } - - /** - * add a footnote to the document - * @param note - * @throws IOException - */ - public XWPFFootnote addFootnote(CTFtnEdn note){ - CTFtnEdn newNote = ctFootnotes.addNewFootnote(); - newNote.set(note); - XWPFFootnote xNote = new XWPFFootnote(newNote, this); + + /** + * add an XWPFFootnote to the document + * + * @param footnote + * @throws IOException + */ + public void addFootnote(XWPFFootnote footnote) { + listFootnote.add(footnote); + ctFootnotes.addNewFootnote().set(footnote.getCTFtnEdn()); + } + + /** + * add a footnote to the document + * + * @param note + * @throws IOException + */ + public XWPFFootnote addFootnote(CTFtnEdn note) { + CTFtnEdn newNote = ctFootnotes.addNewFootnote(); + newNote.set(note); + XWPFFootnote xNote = new XWPFFootnote(newNote, this); listFootnote.add(xNote); - return xNote; - } - - public void setXWPFDocument(XWPFDocument doc) { - document = doc; - } - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getPart() - */ - public XWPFDocument getXWPFDocument() { - if ( document != null) { - return document; - } else { - return (XWPFDocument)getParent(); - } - } -} + return xNote; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getPart() + */ + public XWPFDocument getXWPFDocument() { + if (document != null) { + return document; + } else { + return (XWPFDocument) getParent(); + } + } + + public void setXWPFDocument(XWPFDocument doc) { + document = doc; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java index a07bf4141..2a31247fd 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeader.java @@ -69,14 +69,14 @@ public class XWPFHeader extends XWPFHeaderFooter { cursor.dispose(); } - /** + /** * save and commit footer */ @Override protected void commit() throws IOException { XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "hdr")); - Map map = new HashMap(); + Map map = new HashMap(); map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve"); map.put("urn:schemas-microsoft-com:office:office", "o"); map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); @@ -95,11 +95,12 @@ public class XWPFHeader extends XWPFHeaderFooter { /** * reads the document - * @throws IOException + * + * @throws IOException */ - @Override + @Override protected void onDocumentRead() throws IOException { - super.onDocumentRead(); + super.onDocumentRead(); HdrDocument hdrDocument = null; InputStream is; try { @@ -113,17 +114,17 @@ public class XWPFHeader extends XWPFHeaderFooter { while (cursor.toNextSelection()) { XmlObject o = cursor.getObject(); if (o instanceof CTP) { - XWPFParagraph p = new XWPFParagraph((CTP)o, this); + XWPFParagraph p = new XWPFParagraph((CTP) o, this); paragraphs.add(p); bodyElements.add(p); } if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl)o, this); + XWPFTable t = new XWPFTable((CTTbl) o, this); tables.add(t); bodyElements.add(t); } - if (o instanceof CTSdtBlock){ - XWPFSDT c = new XWPFSDT((CTSdtBlock)o, this); + if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); bodyElements.add(c); } } @@ -135,6 +136,7 @@ public class XWPFHeader extends XWPFHeaderFooter { /** * get the PartType of the body + * * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() */ public BodyType getPartType() { diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java index e6dee2fef..2f96a681c 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java @@ -46,7 +46,7 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; */ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBody { List paragraphs = new ArrayList(1); - List tables= new ArrayList(1); + List tables = new ArrayList(1); List pictures = new ArrayList(); List bodyElements = new ArrayList(1); @@ -54,7 +54,7 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo XWPFDocument document; XWPFHeaderFooter(XWPFDocument doc, CTHdrFtr hdrFtr) { - if (doc==null) { + if (doc == null) { throw new NullPointerException(); } @@ -70,17 +70,17 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo public XWPFHeaderFooter(POIXMLDocumentPart parent, PackagePart part, PackageRelationship rel) throws IOException { super(parent, part, rel); - this.document = (XWPFDocument)getParent(); + this.document = (XWPFDocument) getParent(); - if (this.document==null) { + if (this.document == null) { throw new NullPointerException(); } } @Override protected void onDocumentRead() throws IOException { - for (POIXMLDocumentPart poixmlDocumentPart : getRelations()){ - if(poixmlDocumentPart instanceof XWPFPictureData){ + for (POIXMLDocumentPart poixmlDocumentPart : getRelations()) { + if (poixmlDocumentPart instanceof XWPFPictureData) { XWPFPictureData xwpfPicData = (XWPFPictureData) poixmlDocumentPart; pictures.add(xwpfPicData); document.registerPackagePictureData(xwpfPicData); @@ -93,16 +93,16 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo return headerFooter; } - public List getBodyElements(){ + public List getBodyElements() { return Collections.unmodifiableList(bodyElements); } /** * Returns the paragraph(s) that holds - * the text of the header or footer. + * the text of the header or footer. * Normally there is only the one paragraph, but - * there could be more in certain cases, or - * a table. + * there could be more in certain cases, or + * a table. */ public List getParagraphs() { return Collections.unmodifiableList(paragraphs); @@ -111,29 +111,28 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * Return the table(s) that holds the text - * of the header or footer, for complex cases - * where a paragraph isn't used. + * of the header or footer, for complex cases + * where a paragraph isn't used. * Normally there's just one paragraph, but some - * complex headers/footers have a table or two - * in addition. + * complex headers/footers have a table or two + * in addition. */ - public List getTables()throws ArrayIndexOutOfBoundsException { + public List getTables() throws ArrayIndexOutOfBoundsException { return Collections.unmodifiableList(tables); } - /** * Returns the textual content of the header/footer, - * by flattening out the text of its paragraph(s) + * by flattening out the text of its paragraph(s) */ public String getText() { StringBuffer t = new StringBuffer(); - //TODO: simplify this to get ibody elements in order - for(int i=0; i 0) { + if (text != null && text.length() > 0) { t.append(text); t.append('\n'); } @@ -141,26 +140,26 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo } List tables = getTables(); - for(int i=0; i 0) { + if (text != null && text.length() > 0) { t.append(text); t.append('\n'); } } - - for (IBodyElement bodyElement : getBodyElements()){ - if (bodyElement instanceof XWPFSDT){ - t.append(((XWPFSDT) bodyElement).getContent().getText()+'\n'); - } - } - return t.toString(); + + for (IBodyElement bodyElement : getBodyElements()) { + if (bodyElement instanceof XWPFSDT) { + t.append(((XWPFSDT) bodyElement).getContent().getText() + '\n'); + } + } + return t.toString(); } /** * set a new headerFooter */ - public void setHeaderFooter(CTHdrFtr headerFooter){ + public void setHeaderFooter(CTHdrFtr headerFooter) { this.headerFooter = headerFooter; readHdrFtr(); } @@ -168,14 +167,15 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header * the method will return this table - * if there is no corresponding {@link XWPFTable} the method will return null + * if there is no corresponding {@link XWPFTable} the method will return null + * * @param ctTable */ - public XWPFTable getTable(CTTbl ctTable){ + public XWPFTable getTable(CTTbl ctTable) { for (XWPFTable table : tables) { - if(table==null) + if (table == null) return null; - if(table.getCTTbl().equals(ctTable)) + if (table.getCTTbl().equals(ctTable)) return table; } return null; @@ -184,14 +184,15 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer * the method will return this paragraph - * if there is no corresponding {@link XWPFParagraph} the method will return null + * if there is no corresponding {@link XWPFParagraph} the method will return null + * * @param p is instance of CTP and is searching for an XWPFParagraph * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer - * XWPFParagraph with the correspondig CTP p + * XWPFParagraph with the correspondig CTP p */ - public XWPFParagraph getParagraph(CTP p){ + public XWPFParagraph getParagraph(CTP p) { for (XWPFParagraph paragraph : paragraphs) { - if(paragraph.getCTP().equals(p)) + if (paragraph.getCTP().equals(p)) return paragraph; } return null; @@ -200,7 +201,7 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * Returns the paragraph that holds - * the text of the header or footer. + * the text of the header or footer. */ public XWPFParagraph getParagraphArray(int pos) { @@ -209,9 +210,10 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * get a List of all Paragraphs - * @return a list of {@link XWPFParagraph} + * + * @return a list of {@link XWPFParagraph} */ - public List getListParagraph(){ + public List getListParagraph() { return paragraphs; } @@ -221,9 +223,10 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * get all Pictures in this package + * * @return all Pictures in this package */ - public List getAllPackagePictures(){ + public List getAllPackagePictures() { return document.getAllPackagePictures(); } @@ -231,22 +234,19 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * Adds a picture to the document. * - * @param pictureData The picture data - * @param format The format of the picture. - * + * @param pictureData The picture data + * @param format The format of the picture. * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} . - * @throws InvalidFormatException + * @throws InvalidFormatException */ - public String addPictureData(byte[] pictureData,int format) throws InvalidFormatException - { + public String addPictureData(byte[] pictureData, int format) throws InvalidFormatException { XWPFPictureData xwpfPicData = document.findPackagePictureData(pictureData, format); POIXMLRelation relDesc = XWPFPictureData.RELATIONS[format]; - if (xwpfPicData == null) - { + if (xwpfPicData == null) { /* Part doesn't exist, create a new one */ int idx = document.getNextPicNameNumber(format); - xwpfPicData = (XWPFPictureData) createRelationship(relDesc, XWPFFactory.getInstance(),idx); + xwpfPicData = (XWPFPictureData) createRelationship(relDesc, XWPFFactory.getInstance(), idx); /* write bytes to new part */ PackagePart picDataPart = xwpfPicData.getPackagePart(); OutputStream out = null; @@ -266,9 +266,7 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo document.registerPackagePictureData(xwpfPicData); pictures.add(xwpfPicData); return getRelationId(xwpfPicData); - } - else if (!getRelations().contains(xwpfPicData)) - { + } else if (!getRelations().contains(xwpfPicData)) { /* * Part already existed, but was not related so far. Create * relationship to the already existing part and update @@ -279,14 +277,12 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo TargetMode targetMode = TargetMode.INTERNAL; PackagePartName partName = picDataPart.getPartName(); String relation = relDesc.getRelation(); - PackageRelationship relShip = getPackagePart().addRelationship(partName,targetMode,relation); + PackageRelationship relShip = getPackagePart().addRelationship(partName, targetMode, relation); String id = relShip.getId(); - addRelation(id,xwpfPicData); + addRelation(id, xwpfPicData); pictures.add(xwpfPicData); return id; - } - else - { + } else { /* Part already existed, get relation id and return it */ return getRelationId(xwpfPicData); } @@ -295,61 +291,61 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * Adds a picture to the document. * - * @param is The stream to read image from - * @param format The format of the picture. - * + * @param is The stream to read image from + * @param format The format of the picture. * @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} . - * @throws InvalidFormatException - * @throws IOException + * @throws InvalidFormatException + * @throws IOException */ - public String addPictureData(InputStream is, int format) throws InvalidFormatException,IOException { + public String addPictureData(InputStream is, int format) throws InvalidFormatException, IOException { byte[] data = IOUtils.toByteArray(is); - return addPictureData(data,format); + return addPictureData(data, format); } /** * returns the PictureData by blipID + * * @param blipID * @return XWPFPictureData of a specificID - * @throws Exception + * @throws Exception */ public XWPFPictureData getPictureDataByID(String blipID) { POIXMLDocumentPart relatedPart = getRelationById(blipID); if (relatedPart != null && relatedPart instanceof XWPFPictureData) { return (XWPFPictureData) relatedPart; } - return null; + return null; } /** * add a new paragraph at position of the cursor + * * @param cursor * @return the inserted paragraph */ - public XWPFParagraph insertNewParagraph(XmlCursor cursor){ - if(isCursorInHdrF(cursor)){ + public XWPFParagraph insertNewParagraph(XmlCursor cursor) { + if (isCursorInHdrF(cursor)) { String uri = CTP.type.getName().getNamespaceURI(); String localPart = "p"; - cursor.beginElement(localPart,uri); + cursor.beginElement(localPart, uri); cursor.toParent(); - CTP p = (CTP)cursor.getObject(); + CTP p = (CTP) cursor.getObject(); XWPFParagraph newP = new XWPFParagraph(p, this); XmlObject o = null; - while(!(o instanceof CTP)&&(cursor.toPrevSibling())){ + while (!(o instanceof CTP) && (cursor.toPrevSibling())) { o = cursor.getObject(); } - if((!(o instanceof CTP)) || (CTP)o == p){ + if ((!(o instanceof CTP)) || (CTP) o == p) { paragraphs.add(0, newP); + } else { + int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1; + paragraphs.add(pos, newP); } - else{ - int pos = paragraphs.indexOf(getParagraph((CTP)o))+1; - paragraphs.add(pos,newP); - } - int i=0; + int i = 0; cursor.toCursor(p.newCursor()); - while(cursor.toPrevSibling()){ - o =cursor.getObject(); - if(o instanceof CTP || o instanceof CTTbl) + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) i++; } bodyElements.add(i, newP); @@ -362,35 +358,33 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** - * * @param cursor * @return the inserted table */ public XWPFTable insertNewTbl(XmlCursor cursor) { - if(isCursorInHdrF(cursor)){ + if (isCursorInHdrF(cursor)) { String uri = CTTbl.type.getName().getNamespaceURI(); String localPart = "tbl"; - cursor.beginElement(localPart,uri); + cursor.beginElement(localPart, uri); cursor.toParent(); - CTTbl t = (CTTbl)cursor.getObject(); + CTTbl t = (CTTbl) cursor.getObject(); XWPFTable newT = new XWPFTable(t, this); cursor.removeXmlContents(); XmlObject o = null; - while(!(o instanceof CTTbl)&&(cursor.toPrevSibling())){ + while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) { o = cursor.getObject(); } - if(!(o instanceof CTTbl)){ + if (!(o instanceof CTTbl)) { tables.add(0, newT); + } else { + int pos = tables.indexOf(getTable((CTTbl) o)) + 1; + tables.add(pos, newT); } - else{ - int pos = tables.indexOf(getTable((CTTbl)o))+1; - tables.add(pos,newT); - } - int i=0; + int i = 0; cursor = t.newCursor(); - while(cursor.toPrevSibling()){ - o =cursor.getObject(); - if(o instanceof CTP || o instanceof CTTbl) + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) i++; } bodyElements.add(i, newT); @@ -403,29 +397,31 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * verifies that cursor is on the right position + * * @param cursor */ private boolean isCursorInHdrF(XmlCursor cursor) { XmlCursor verify = cursor.newCursor(); verify.toParent(); - if(verify.getObject() == this.headerFooter){ + if (verify.getObject() == this.headerFooter) { return true; } return false; } - public POIXMLDocumentPart getOwner(){ + public POIXMLDocumentPart getOwner() { return this; } /** * Returns the table at position pos + * * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int) */ public XWPFTable getTableArray(int pos) { - if(pos > 0 && pos < tables.size()){ + if (pos > 0 && pos < tables.size()) { return tables.get(pos); } return null; @@ -433,6 +429,7 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * inserts an existing XWPFTable to the arrays bodyElements and tables + * * @param pos * @param table */ @@ -441,7 +438,7 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo bodyElements.add(pos, table); int i = 0; for (CTTbl tbl : headerFooter.getTblArray()) { - if(tbl == table.getCTTbl()){ + if (tbl == table.getCTTbl()) { break; } i++; @@ -450,10 +447,10 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo } - public void readHdrFtr(){ + public void readHdrFtr() { bodyElements = new ArrayList(); paragraphs = new ArrayList(); - tables= new ArrayList(); + tables = new ArrayList(); // parse the document with cursor and add // the XmlObject to its lists XmlCursor cursor = headerFooter.newCursor(); @@ -461,12 +458,12 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo while (cursor.toNextSelection()) { XmlObject o = cursor.getObject(); if (o instanceof CTP) { - XWPFParagraph p = new XWPFParagraph((CTP)o, this); + XWPFParagraph p = new XWPFParagraph((CTP) o, this); paragraphs.add(p); bodyElements.add(p); } if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl)o, this); + XWPFTable t = new XWPFTable((CTTbl) o, this); tables.add(t); bodyElements.add(t); } @@ -476,48 +473,50 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo /** * get the TableCell which belongs to the TableCell + * * @param cell */ public XWPFTableCell getTableCell(CTTc cell) { XmlCursor cursor = cell.newCursor(); cursor.toParent(); XmlObject o = cursor.getObject(); - if(!(o instanceof CTRow)){ + if (!(o instanceof CTRow)) { return null; } - CTRow row = (CTRow)o; + CTRow row = (CTRow) o; cursor.toParent(); o = cursor.getObject(); cursor.dispose(); - if(! (o instanceof CTTbl)){ + if (!(o instanceof CTTbl)) { return null; } CTTbl tbl = (CTTbl) o; XWPFTable table = getTable(tbl); - if(table == null){ + if (table == null) { return null; } XWPFTableRow tableRow = table.getRow(row); - if(row == null){ + if (row == null) { return null; } return tableRow.getTableCell(cell); } + public XWPFDocument getXWPFDocument() { + if (document != null) { + return document; + } else { + return (XWPFDocument) getParent(); + } + } + public void setXWPFDocument(XWPFDocument doc) { document = doc; } - public XWPFDocument getXWPFDocument() { - if (document!=null) { - return document; - } else { - return (XWPFDocument)getParent(); - } - } - /** * returns the Part, to which the body belongs, which you need for adding relationship to other parts + * * @see org.apache.poi.xwpf.usermodel.IBody#getPart() */ public POIXMLDocumentPart getPart() { diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlink.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlink.java index f9f2f9d32..c00f75a89 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlink.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlink.java @@ -18,26 +18,22 @@ package org.apache.poi.xwpf.usermodel; /** * Sketch of XWPF hyperlink class - * -* @author Yury Batrakov (batrakov at gmail.com) - * + * + * @author Yury Batrakov (batrakov at gmail.com) */ -public class XWPFHyperlink -{ +public class XWPFHyperlink { String id, url; - public XWPFHyperlink(String id, String url) - { + + public XWPFHyperlink(String id, String url) { this.id = id; this.url = url; } - - public String getId() - { + + public String getId() { return id; } - - public String getURL() - { + + public String getURL() { return url; } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlinkRun.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlinkRun.java index 2461d3324..4c8158a41 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlinkRun.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFHyperlinkRun.java @@ -20,45 +20,45 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; /** - * A run of text with a Hyperlink applied to it. - * Any given Hyperlink may be made up of multiple of these. - */ -public class XWPFHyperlinkRun extends XWPFRun -{ - private CTHyperlink hyperlink; - - public XWPFHyperlinkRun(CTHyperlink hyperlink, CTR run, IRunBody p) { - super(run, p); - this.hyperlink = hyperlink; - } - - public CTHyperlink getCTHyperlink() { - return hyperlink; - } - - public String getAnchor() { - return hyperlink.getAnchor(); - } - - /** - * Returns the ID of the hyperlink, if one is set. - */ - public String getHyperlinkId() { - return hyperlink.getId(); - } - public void setHyperlinkId(String id) { - hyperlink.setId(id); - } - - /** - * If this Hyperlink is an external reference hyperlink, - * return the object for it. - */ - public XWPFHyperlink getHyperlink(XWPFDocument document) { - String id = getHyperlinkId(); - if(id == null) - return null; - - return document.getHyperlinkByID(id); - } -} + * A run of text with a Hyperlink applied to it. + * Any given Hyperlink may be made up of multiple of these. + */ +public class XWPFHyperlinkRun extends XWPFRun { + private CTHyperlink hyperlink; + + public XWPFHyperlinkRun(CTHyperlink hyperlink, CTR run, IRunBody p) { + super(run, p); + this.hyperlink = hyperlink; + } + + public CTHyperlink getCTHyperlink() { + return hyperlink; + } + + public String getAnchor() { + return hyperlink.getAnchor(); + } + + /** + * Returns the ID of the hyperlink, if one is set. + */ + public String getHyperlinkId() { + return hyperlink.getId(); + } + + public void setHyperlinkId(String id) { + hyperlink.setId(id); + } + + /** + * If this Hyperlink is an external reference hyperlink, + * return the object for it. + */ + public XWPFHyperlink getHyperlink(XWPFDocument document) { + String id = getHyperlinkId(); + if (id == null) + return null; + + return document.getHyperlinkByID(id); + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFLatentStyles.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFLatentStyles.java index 83b898c1b..ab802ffbc 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFLatentStyles.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFLatentStyles.java @@ -17,34 +17,38 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLatentStyles; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLsdException; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLsdException; + +public class XWPFLatentStyles { + protected XWPFStyles styles; //LatentStyle shall know styles + private CTLatentStyles latentStyles; + + protected XWPFLatentStyles() { + } + + protected XWPFLatentStyles(CTLatentStyles latentStyles) { + this(latentStyles, null); + } + + protected XWPFLatentStyles(CTLatentStyles latentStyles, XWPFStyles styles) { + this.latentStyles = latentStyles; + this.styles = styles; + } + + public int getNumberOfStyles() { + return latentStyles.sizeOfLsdExceptionArray(); + } -public class XWPFLatentStyles { - private CTLatentStyles latentStyles; - protected XWPFStyles styles; //LatentStyle shall know styles - - protected XWPFLatentStyles(){ - } - - protected XWPFLatentStyles(CTLatentStyles latentStyles){ - this(latentStyles,null); - } - - protected XWPFLatentStyles(CTLatentStyles latentStyles, XWPFStyles styles) { - this.latentStyles=latentStyles; - this.styles=styles; - } - - /** - * checks wheter specific LatentStyleID is a latentStyle - */ - @SuppressWarnings("deprecation") - protected boolean isLatentStyle(String latentStyleID){ - for ( CTLsdException lsd: latentStyles.getLsdExceptionArray()) { - if(lsd.getName().equals(latentStyleID)) { - return true; - } - } - return false; - } -} + /** + * checks whether specific LatentStyleID is a latentStyle + */ + @SuppressWarnings("deprecation") + protected boolean isLatentStyle(String latentStyleID) { + for (CTLsdException lsd : latentStyles.getLsdExceptionArray()) { + if (lsd.getName().equals(latentStyleID)) { + return true; + } + } + return false; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNum.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNum.java index 300936d2a..b1ae7ed8c 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNum.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNum.java @@ -18,48 +18,47 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNum; - -/** - * @author Philipp Epp - * - */ -public class XWPFNum { - private CTNum ctNum; - protected XWPFNumbering numbering; - - public XWPFNum(){ - this.ctNum = null; - this.numbering = null; - } - - public XWPFNum(CTNum ctNum){ - this.ctNum = ctNum; - this.numbering = null; - } - - public XWPFNum(XWPFNumbering numbering){ - this.ctNum = null; - this.numbering = numbering; - } - - public XWPFNum(CTNum ctNum, XWPFNumbering numbering){ - this.ctNum = ctNum; - this.numbering = numbering; - } - - public XWPFNumbering getNumbering(){ - return numbering; - } - - public CTNum getCTNum(){ - return ctNum; - } - - public void setNumbering(XWPFNumbering numbering){ - this.numbering = numbering; - } - - public void setCTNum(CTNum ctNum){ - this.ctNum = ctNum; - } + +/** + * @author Philipp Epp + */ +public class XWPFNum { + protected XWPFNumbering numbering; + private CTNum ctNum; + + public XWPFNum() { + this.ctNum = null; + this.numbering = null; + } + + public XWPFNum(CTNum ctNum) { + this.ctNum = ctNum; + this.numbering = null; + } + + public XWPFNum(XWPFNumbering numbering) { + this.ctNum = null; + this.numbering = numbering; + } + + public XWPFNum(CTNum ctNum, XWPFNumbering numbering) { + this.ctNum = ctNum; + this.numbering = numbering; + } + + public XWPFNumbering getNumbering() { + return numbering; + } + + public void setNumbering(XWPFNumbering numbering) { + this.numbering = numbering; + } + + public CTNum getCTNum() { + return ctNum; + } + + public void setCTNum(CTNum ctNum) { + this.ctNum = ctNum; + } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java index 1bc8af5ae..842bb4434 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFNumbering.java @@ -38,71 +38,69 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNum; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering; import org.openxmlformats.schemas.wordprocessingml.x2006.main.NumberingDocument; - -/** - * @author Philipp Epp - * - */ -public class XWPFNumbering extends POIXMLDocumentPart { - protected List abstractNums = new ArrayList(); - protected List nums = new ArrayList(); - - private CTNumbering ctNumbering; - boolean isNew; - - /** - *create a new styles object with an existing document - */ - public XWPFNumbering(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException{ - super(part, rel); - isNew = true; - } - - /** - * create a new XWPFNumbering object for use in a new document - */ - public XWPFNumbering(){ - abstractNums = new ArrayList(); - nums = new ArrayList(); - isNew = true; - } - - /** - * read numbering form an existing package - */ - @Override - @SuppressWarnings("deprecation") - protected void onDocumentRead() throws IOException{ - NumberingDocument numberingDoc = null; - InputStream is; - is = getPackagePart().getInputStream(); - try { - numberingDoc = NumberingDocument.Factory.parse(is); - ctNumbering = numberingDoc.getNumbering(); - //get any Nums - for(CTNum ctNum : ctNumbering.getNumArray()) { - nums.add(new XWPFNum(ctNum, this)); - } - for(CTAbstractNum ctAbstractNum : ctNumbering.getAbstractNumArray()){ - abstractNums.add(new XWPFAbstractNum(ctAbstractNum, this)); - } - isNew = false; - } catch (XmlException e) { - throw new POIXMLException(); - } - } - - /** - * save and commit numbering - */ - @Override - protected void commit() throws IOException { - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "numbering")); - Map map = new HashMap(); - map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve"); - map.put("urn:schemas-microsoft-com:office:office", "o"); - map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); + +/** + * @author Philipp Epp + */ +public class XWPFNumbering extends POIXMLDocumentPart { + protected List abstractNums = new ArrayList(); + protected List nums = new ArrayList(); + boolean isNew; + private CTNumbering ctNumbering; + + /** + * create a new styles object with an existing document + */ + public XWPFNumbering(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException { + super(part, rel); + isNew = true; + } + + /** + * create a new XWPFNumbering object for use in a new document + */ + public XWPFNumbering() { + abstractNums = new ArrayList(); + nums = new ArrayList(); + isNew = true; + } + + /** + * read numbering form an existing package + */ + @Override + @SuppressWarnings("deprecation") + protected void onDocumentRead() throws IOException { + NumberingDocument numberingDoc = null; + InputStream is; + is = getPackagePart().getInputStream(); + try { + numberingDoc = NumberingDocument.Factory.parse(is); + ctNumbering = numberingDoc.getNumbering(); + //get any Nums + for (CTNum ctNum : ctNumbering.getNumArray()) { + nums.add(new XWPFNum(ctNum, this)); + } + for (CTAbstractNum ctAbstractNum : ctNumbering.getAbstractNumArray()) { + abstractNums.add(new XWPFAbstractNum(ctAbstractNum, this)); + } + isNew = false; + } catch (XmlException e) { + throw new POIXMLException(); + } + } + + /** + * save and commit numbering + */ + @Override + protected void commit() throws IOException { + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + xmlOptions.setSaveSyntheticDocumentElement(new QName(CTNumbering.type.getName().getNamespaceURI(), "numbering")); + Map map = new HashMap(); + map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", "ve"); + map.put("urn:schemas-microsoft-com:office:office", "o"); + map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); map.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m"); map.put("urn:schemas-microsoft-com:vml", "v"); map.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "wp"); @@ -114,169 +112,182 @@ public class XWPFNumbering extends POIXMLDocumentPart { OutputStream out = part.getOutputStream(); ctNumbering.save(out, xmlOptions); out.close(); - } - - - /** - * Sets the ctNumbering - * @param numbering - */ - public void setNumbering(CTNumbering numbering){ - ctNumbering = numbering; - } - - - /** - * Checks whether number with numID exists - * @param numID - * @return boolean true if num exist, false if num not exist - */ - public boolean numExist(BigInteger numID){ - for (XWPFNum num : nums) { - if (num.getCTNum().getNumId().equals(numID)) - return true; - } - return false; - } - - /** - * add a new number to the numbering document - * @param num - */ - public BigInteger addNum(XWPFNum num){ - ctNumbering.addNewNum(); - int pos = ctNumbering.sizeOfNumArray() - 1; - ctNumbering.setNumArray(pos, num.getCTNum()); - nums.add(num); - return num.getCTNum().getNumId(); - } - - /** - * Add a new num with an abstractNumID - * @return return NumId of the added num - */ - public BigInteger addNum(BigInteger abstractNumID){ - CTNum ctNum = this.ctNumbering.addNewNum(); - ctNum.addNewAbstractNumId(); - ctNum.getAbstractNumId().setVal(abstractNumID); - ctNum.setNumId(BigInteger.valueOf(nums.size()+1)); - XWPFNum num = new XWPFNum(ctNum, this); - nums.add(num); - return ctNum.getNumId(); - } - - /** - * Add a new num with an abstractNumID and a numID - * @param abstractNumID - * @param numID - */ - public void addNum(BigInteger abstractNumID, BigInteger numID){ - CTNum ctNum = this.ctNumbering.addNewNum(); - ctNum.addNewAbstractNumId(); - ctNum.getAbstractNumId().setVal(abstractNumID); - ctNum.setNumId(numID); - XWPFNum num = new XWPFNum(ctNum, this); - nums.add(num); - } - - /** - * get Num by NumID - * @param numID - * @return abstractNum with NumId if no Num exists with that NumID - * null will be returned - */ - public XWPFNum getNum(BigInteger numID){ - for(XWPFNum num: nums){ - if(num.getCTNum().getNumId().equals(numID)) - return num; - } - return null; - } - /** - * get AbstractNum by abstractNumID - * @param abstractNumID - * @return abstractNum with abstractNumId if no abstractNum exists with that abstractNumID - * null will be returned - */ - public XWPFAbstractNum getAbstractNum(BigInteger abstractNumID){ - for(XWPFAbstractNum abstractNum: abstractNums){ - if(abstractNum.getAbstractNum().getAbstractNumId().equals(abstractNumID)){ - return abstractNum; - } - } - return null; - } - /** - * Compare AbstractNum with abstractNums of this numbering document. - * If the content of abstractNum equals with an abstractNum of the List in numbering - * the BigInteger Value of it will be returned. - * If no equal abstractNum is existing null will be returned - * - * @param abstractNum - * @return BigInteger - */ - public BigInteger getIdOfAbstractNum(XWPFAbstractNum abstractNum){ - CTAbstractNum copy = (CTAbstractNum) abstractNum.getCTAbstractNum().copy(); - XWPFAbstractNum newAbstractNum = new XWPFAbstractNum(copy, this); - int i; - for (i = 0; i < abstractNums.size(); i++) { - newAbstractNum.getCTAbstractNum().setAbstractNumId(BigInteger.valueOf(i)); - newAbstractNum.setNumbering(this); - if(newAbstractNum.getCTAbstractNum().valueEquals(abstractNums.get(i).getCTAbstractNum())){ - return newAbstractNum.getCTAbstractNum().getAbstractNumId(); - } - } - return null; - } - - - /** - * add a new AbstractNum and return its AbstractNumID - * @param abstractNum - */ - public BigInteger addAbstractNum(XWPFAbstractNum abstractNum){ - int pos = abstractNums.size(); - if(abstractNum.getAbstractNum() != null){ // Use the current CTAbstractNum if it exists - ctNumbering.addNewAbstractNum().set(abstractNum.getAbstractNum()); - } else { - ctNumbering.addNewAbstractNum(); - abstractNum.getAbstractNum().setAbstractNumId(BigInteger.valueOf(pos)); - ctNumbering.setAbstractNumArray(pos, abstractNum.getAbstractNum()); - } - abstractNums.add(abstractNum); - return abstractNum.getCTAbstractNum().getAbstractNumId(); - } - - /** - * remove an existing abstractNum - * @param abstractNumID - * @return true if abstractNum with abstractNumID exists in NumberingArray, - * false if abstractNum with abstractNumID not exists - */ - public boolean removeAbstractNum(BigInteger abstractNumID){ - if(abstractNumID.byteValue()A Paragraph within a Document, Table, Header etc.

    - * + *

    A Paragraph within a Document, Table, Header etc.

    + *

    *

    A paragraph has a lot of styling information, but the - * actual text (possibly along with more styling) is held on - * the child {@link XWPFRun}s.

    + * actual text (possibly along with more styling) is held on + * the child {@link XWPFRun}s.

    */ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Paragraph { private final CTP paragraph; protected IBody part; - /** For access to the document's hyperlink, comments, tables etc */ + /** + * For access to the document's hyperlink, comments, tables etc + */ protected XWPFDocument document; protected List runs; protected List iruns; @@ -75,10 +80,10 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para public XWPFParagraph(CTP prgrph, IBody part) { this.paragraph = prgrph; this.part = part; - + this.document = part.getXWPFDocument(); - if (document==null) { + if (document == null) { throw new NullPointerException(); } @@ -88,7 +93,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para buildRunsInOrderFromXml(paragraph); // Look for bits associated with the runs - for(XWPFRun run : runs) { + for (XWPFRun run : runs) { CTR r = run.getCTR(); // Check for bits that only apply when attached to a core document @@ -97,13 +102,13 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para c.selectPath("child::*"); while (c.toNextSelection()) { XmlObject o = c.getObject(); - if(o instanceof CTFtnEdnRef) { - CTFtnEdnRef ftn = (CTFtnEdnRef)o; + if (o instanceof CTFtnEdnRef) { + CTFtnEdnRef ftn = (CTFtnEdnRef) o; footnoteText.append(" [").append(ftn.getId()).append(": "); XWPFFootnote footnote = - ftn.getDomNode().getLocalName().equals("footnoteReference") ? - document.getFootnoteByID(ftn.getId().intValue()) : - document.getEndnoteByID(ftn.getId().intValue()); + ftn.getDomNode().getLocalName().equals("footnoteReference") ? + document.getFootnoteByID(ftn.getId().intValue()) : + document.getEndnoteByID(ftn.getId().intValue()); boolean first = true; for (XWPFParagraph p : footnote.getParagraphs()) { @@ -123,8 +128,8 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * Identifies (in order) the parts of the paragraph / - * sub-paragraph that correspond to character text - * runs, and builds the appropriate runs for these. + * sub-paragraph that correspond to character text + * runs, and builds the appropriate runs for these. */ private void buildRunsInOrderFromXml(XmlObject object) { XmlCursor c = object.newCursor(); @@ -132,71 +137,72 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para while (c.toNextSelection()) { XmlObject o = c.getObject(); if (o instanceof CTR) { - XWPFRun r = new XWPFRun((CTR) o, this); - runs.add(r); - iruns.add(r); - } - if (o instanceof CTHyperlink) { - CTHyperlink link = (CTHyperlink) o; - for (CTR r : link.getRArray()) { - XWPFHyperlinkRun hr = new XWPFHyperlinkRun(link, r, this); - runs.add(hr); - iruns.add(hr); - } - } - if (o instanceof CTSdtBlock) { - XWPFSDT cc = new XWPFSDT((CTSdtBlock) o, part); - iruns.add(cc); - } - if (o instanceof CTSdtRun) { - XWPFSDT cc = new XWPFSDT((CTSdtRun) o, part); - iruns.add(cc); - } - if (o instanceof CTRunTrackChange) { - for (CTR r : ((CTRunTrackChange) o).getRArray()) { - XWPFRun cr = new XWPFRun(r, this); - runs.add(cr); - iruns.add(cr); - } - } - if (o instanceof CTSimpleField) { - for (CTR r : ((CTSimpleField) o).getRArray()) { - XWPFRun cr = new XWPFRun(r, this); - runs.add(cr); - iruns.add(cr); - } - } + XWPFRun r = new XWPFRun((CTR) o, this); + runs.add(r); + iruns.add(r); + } + if (o instanceof CTHyperlink) { + CTHyperlink link = (CTHyperlink) o; + for (CTR r : link.getRArray()) { + XWPFHyperlinkRun hr = new XWPFHyperlinkRun(link, r, this); + runs.add(hr); + iruns.add(hr); + } + } + if (o instanceof CTSdtBlock) { + XWPFSDT cc = new XWPFSDT((CTSdtBlock) o, part); + iruns.add(cc); + } + if (o instanceof CTSdtRun) { + XWPFSDT cc = new XWPFSDT((CTSdtRun) o, part); + iruns.add(cc); + } + if (o instanceof CTRunTrackChange) { + for (CTR r : ((CTRunTrackChange) o).getRArray()) { + XWPFRun cr = new XWPFRun(r, this); + runs.add(cr); + iruns.add(cr); + } + } + if (o instanceof CTSimpleField) { + for (CTR r : ((CTSimpleField) o).getRArray()) { + XWPFRun cr = new XWPFRun(r, this); + runs.add(cr); + iruns.add(cr); + } + } if (o instanceof CTSmartTagRun) { - // Smart Tags can be nested many times. + // Smart Tags can be nested many times. // This implementation does not preserve the tagging information buildRunsInOrderFromXml(o); } } c.dispose(); } - + @Internal public CTP getCTP() { return paragraph; } - public List getRuns(){ + public List getRuns() { return Collections.unmodifiableList(runs); } - + /** * Return literal runs and sdt/content control objects. + * * @return List */ public List getIRuns() { return Collections.unmodifiableList(iruns); } - - public boolean isEmpty(){ + + public boolean isEmpty() { return !paragraph.getDomNode().hasChildNodes(); } - public XWPFDocument getDocument(){ + public XWPFDocument getDocument() { return document; } @@ -207,8 +213,8 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para public String getText() { StringBuffer out = new StringBuffer(); for (IRunElement run : iruns) { - if (run instanceof XWPFSDT){ - out.append(((XWPFSDT)run).getContent().getText()); + if (run instanceof XWPFSDT) { + out.append(((XWPFSDT) run).getContent().getText()); } else { out.append(run.toString()); } @@ -219,43 +225,63 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * Return styleID of the paragraph if style exist for this paragraph - * if not, null will be returned - * @return styleID as String + * if not, null will be returned + * + * @return styleID as String */ public String getStyleID() { if (paragraph.getPPr() != null) { - if(paragraph.getPPr().getPStyle()!= null) { - if (paragraph.getPPr().getPStyle().getVal()!= null) + if (paragraph.getPPr().getPStyle() != null) { + if (paragraph.getPPr().getPStyle().getVal() != null) return paragraph.getPPr().getPStyle().getVal(); } } return null; - } + } + /** * If style exist for this paragraph * NumId of the paragraph will be returned. - * If style not exist null will be returned - * @return NumID as BigInteger + * If style not exist null will be returned + * + * @return NumID as BigInteger */ - public BigInteger getNumID(){ - if(paragraph.getPPr()!=null){ - if(paragraph.getPPr().getNumPr()!=null){ - if(paragraph.getPPr().getNumPr().getNumId()!=null) + public BigInteger getNumID() { + if (paragraph.getPPr() != null) { + if (paragraph.getPPr().getNumPr() != null) { + if (paragraph.getPPr().getNumPr().getNumId() != null) return paragraph.getPPr().getNumPr().getNumId().getVal(); } } return null; } + /** + * setNumID of Paragraph + * + * @param numPos + */ + public void setNumID(BigInteger numPos) { + if (paragraph.getPPr() == null) + paragraph.addNewPPr(); + if (paragraph.getPPr().getNumPr() == null) + paragraph.getPPr().addNewNumPr(); + if (paragraph.getPPr().getNumPr().getNumId() == null) { + paragraph.getPPr().getNumPr().addNewNumId(); + } + paragraph.getPPr().getNumPr().getNumId().setVal(numPos); + } + /** * Returns Ilvl of the numeric style for this paragraph. * Returns null if this paragraph does not have numeric style. + * * @return Ilvl as BigInteger */ public BigInteger getNumIlvl() { - if(paragraph.getPPr()!=null){ - if(paragraph.getPPr().getNumPr()!=null){ - if(paragraph.getPPr().getNumPr().getIlvl()!=null) + if (paragraph.getPPr() != null) { + if (paragraph.getPPr().getNumPr() != null) { + if (paragraph.getPPr().getNumPr().getIlvl() != null) return paragraph.getPPr().getNumPr().getIlvl().getVal(); } } @@ -264,27 +290,28 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * Returns numbering format for this paragraph, eg bullet or - * lowerLetter. + * lowerLetter. * Returns null if this paragraph does not have numeric style. */ public String getNumFmt() { BigInteger numID = getNumID(); XWPFNumbering numbering = document.getNumbering(); - if(numID != null && numbering != null) { + if (numID != null && numbering != null) { XWPFNum num = numbering.getNum(numID); - if(num != null) { + if (num != null) { BigInteger ilvl = getNumIlvl(); BigInteger abstractNumId = num.getCTNum().getAbstractNumId().getVal(); CTAbstractNum anum = numbering.getAbstractNum(abstractNumId).getAbstractNum(); CTLvl level = null; - for(int i = 0; i < anum.sizeOfLvlArray(); i++) { + for (int i = 0; i < anum.sizeOfLvlArray(); i++) { CTLvl lvl = anum.getLvlArray(i); - if(lvl.getIlvl().equals(ilvl)) { + if (lvl.getIlvl().equals(ilvl)) { level = lvl; break; } } - if(level != null) + if (level != null && level.getNumFmt() != null + && level.getNumFmt().getVal() != null) return level.getNumFmt().getVal().toString(); } } @@ -292,18 +319,87 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * setNumID of Paragraph - * @param numPos + * Returns the text that should be used around the paragraph level numbers. + * + * @return a string (e.g. "%1.") or null if the value is not found. */ - public void setNumID(BigInteger numPos) { - if(paragraph.getPPr()==null) - paragraph.addNewPPr(); - if(paragraph.getPPr().getNumPr()==null) - paragraph.getPPr().addNewNumPr(); - if(paragraph.getPPr().getNumPr().getNumId()==null){ - paragraph.getPPr().getNumPr().addNewNumId(); + public String getNumLevelText() { + BigInteger numID = getNumID(); + XWPFNumbering numbering = document.getNumbering(); + if (numID != null && numbering != null) { + XWPFNum num = numbering.getNum(numID); + if (num != null) { + BigInteger ilvl = getNumIlvl(); + CTNum ctNum = num.getCTNum(); + if (ctNum == null) + return null; + + CTDecimalNumber ctDecimalNumber = ctNum.getAbstractNumId(); + if (ctDecimalNumber == null) + return null; + + BigInteger abstractNumId = ctDecimalNumber.getVal(); + if (abstractNumId == null) + return null; + + XWPFAbstractNum xwpfAbstractNum = numbering.getAbstractNum(abstractNumId); + + if (xwpfAbstractNum == null) + return null; + + CTAbstractNum anum = xwpfAbstractNum.getCTAbstractNum(); + + if (anum == null) + return null; + + CTLvl level = null; + for (int i = 0; i < anum.sizeOfLvlArray(); i++) { + CTLvl lvl = anum.getLvlArray(i); + if (lvl != null && lvl.getIlvl() != null && lvl.getIlvl().equals(ilvl)) { + level = lvl; + break; + } + } + if (level != null && level.getLvlText() != null + && level.getLvlText().getVal() != null) + return level.getLvlText().getVal().toString(); + } } - paragraph.getPPr().getNumPr().getNumId().setVal(numPos); + return null; + } + + /** + * Gets the numstartOverride for the paragraph numbering for this paragraph. + * + * @return returns the overridden start number or null if there is no override for this paragraph. + */ + public BigInteger getNumStartOverride() { + BigInteger numID = getNumID(); + XWPFNumbering numbering = document.getNumbering(); + if (numID != null && numbering != null) { + XWPFNum num = numbering.getNum(numID); + + if (num != null) { + CTNum ctNum = num.getCTNum(); + if (ctNum == null) { + return null; + } + BigInteger ilvl = getNumIlvl(); + CTNumLvl level = null; + for (int i = 0; i < ctNum.sizeOfLvlOverrideArray(); i++) { + CTNumLvl ctNumLvl = ctNum.getLvlOverrideArray(i); + if (ctNumLvl != null && ctNumLvl.getIlvl() != null && + ctNumLvl.getIlvl().equals(ilvl)) { + level = ctNumLvl; + break; + } + } + if (level != null && level.getStartOverride() != null) { + return level.getStartOverride().getVal(); + } + } + } + return null; } /** @@ -312,7 +408,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para */ public String getParagraphText() { StringBuffer out = new StringBuffer(); - for(XWPFRun run : runs) { + for (XWPFRun run : runs) { out.append(run.toString()); } return out.toString(); @@ -323,7 +419,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para */ public String getPictureText() { StringBuffer out = new StringBuffer(); - for(XWPFRun run : runs) { + for (XWPFRun run : runs) { out.append(run.getPictureText()); } return out.toString(); @@ -332,7 +428,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * Returns the footnote text of the paragraph * - * @return the footnote text or empty string if the paragraph does not have footnotes + * @return the footnote text or empty string if the paragraph does not have footnotes */ public String getFootnoteText() { return footnoteText.toString(); @@ -385,6 +481,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para public int getFontAlignment() { return getAlignment().getValue(); } + public void setFontAlignment(int align) { ParagraphAlignment pAlign = ParagraphAlignment.valueOf(align); setAlignment(pAlign); @@ -412,7 +509,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para CTPPr pr = getCTPPr(); return (pr == null || !pr.isSetTextAlignment()) ? TextAlignment.AUTO : TextAlignment.valueOf(pr.getTextAlignment().getVal() - .intValue()); + .intValue()); } /** @@ -438,9 +535,27 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para CTPPr pr = getCTPPr(); CTTextAlignment textAlignment = pr.isSetTextAlignment() ? pr .getTextAlignment() : pr.addNewTextAlignment(); - STTextAlignment.Enum en = STTextAlignment.Enum - .forInt(valign.getValue()); - textAlignment.setVal(en); + STTextAlignment.Enum en = STTextAlignment.Enum + .forInt(valign.getValue()); + textAlignment.setVal(en); + } + + /** + * Specifies the border which shall be displayed above a set of paragraphs + * which have the same set of paragraph border settings. + * + * @return paragraphBorder - the top border for the paragraph + * @see #setBorderTop(Borders) + * @see Borders a list of all types of borders + */ + public Borders getBorderTop() { + CTPBdr border = getCTPBrd(false); + CTBorder ct = null; + if (border != null) { + ct = border.getTop(); + } + STBorder.Enum ptrn = (ct != null) ? ct.getVal() : STBorder.NONE; + return Borders.valueOf(ptrn.intValue()); } /** @@ -484,20 +599,20 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies the border which shall be displayed above a set of paragraphs - * which have the same set of paragraph border settings. + * Specifies the border which shall be displayed below a set of + * paragraphs which have the same set of paragraph border settings. * - * @return paragraphBorder - the top border for the paragraph - * @see #setBorderTop(Borders) + * @return paragraphBorder - the bottom border for the paragraph + * @see #setBorderBottom(Borders) * @see Borders a list of all types of borders */ - public Borders getBorderTop() { + public Borders getBorderBottom() { CTPBdr border = getCTPBrd(false); CTBorder ct = null; if (border != null) { - ct = border.getTop(); + ct = border.getBottom(); } - STBorder.Enum ptrn = (ct != null) ? ct.getVal() : STBorder.NONE; + STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE; return Borders.valueOf(ptrn.intValue()); } @@ -538,18 +653,18 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies the border which shall be displayed below a set of - * paragraphs which have the same set of paragraph border settings. + * Specifies the border which shall be displayed on the left side of the + * page around the specified paragraph. * - * @return paragraphBorder - the bottom border for the paragraph - * @see #setBorderBottom(Borders) - * @see Borders a list of all types of borders + * @return ParagraphBorder - the left border for the paragraph + * @see #setBorderLeft(Borders) + * @see Borders for a list of all possible borders */ - public Borders getBorderBottom() { + public Borders getBorderLeft() { CTPBdr border = getCTPBrd(false); CTBorder ct = null; if (border != null) { - ct = border.getBottom(); + ct = border.getLeft(); } STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE; return Borders.valueOf(ptrn.intValue()); @@ -587,18 +702,18 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies the border which shall be displayed on the left side of the + * Specifies the border which shall be displayed on the right side of the * page around the specified paragraph. * - * @return ParagraphBorder - the left border for the paragraph - * @see #setBorderLeft(Borders) + * @return ParagraphBorder - the right border for the paragraph + * @see #setBorderRight(Borders) * @see Borders for a list of all possible borders */ - public Borders getBorderLeft() { + public Borders getBorderRight() { CTPBdr border = getCTPBrd(false); CTBorder ct = null; if (border != null) { - ct = border.getLeft(); + ct = border.getRight(); } STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE; return Borders.valueOf(ptrn.intValue()); @@ -636,18 +751,18 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies the border which shall be displayed on the right side of the - * page around the specified paragraph. + * Specifies the border which shall be displayed between each paragraph in a + * set of paragraphs which have the same set of paragraph border settings. * - * @return ParagraphBorder - the right border for the paragraph - * @see #setBorderRight(Borders) + * @return ParagraphBorder - the between border for the paragraph + * @see #setBorderBetween(Borders) * @see Borders for a list of all possible borders */ - public Borders getBorderRight() { + public Borders getBorderBetween() { CTPBdr border = getCTPBrd(false); CTBorder ct = null; if (border != null) { - ct = border.getRight(); + ct = border.getBetween(); } STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE; return Borders.valueOf(ptrn.intValue()); @@ -689,21 +804,29 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies the border which shall be displayed between each paragraph in a - * set of paragraphs which have the same set of paragraph border settings. + * Specifies that when rendering this document in a paginated + * view, the contents of this paragraph are rendered on the start of a new + * page in the document. + *

    + * If this element is omitted on a given paragraph, + * its value is determined by the setting previously set at any level of the + * style hierarchy (i.e. that previous setting remains unchanged). If this + * setting is never specified in the style hierarchy, then this property + * shall not be applied. Since the paragraph is specified to start on a new + * page, it begins page two even though it could have fit on page one. + *

    * - * @return ParagraphBorder - the between border for the paragraph - * @see #setBorderBetween(Borders) - * @see Borders for a list of all possible borders + * @return boolean - if page break is set */ - public Borders getBorderBetween() { - CTPBdr border = getCTPBrd(false); - CTBorder ct = null; - if (border != null) { - ct = border.getBetween(); + public boolean isPageBreak() { + CTPPr ppr = getCTPPr(); + CTOnOff ct_pageBreak = ppr.isSetPageBreakBefore() ? ppr + .getPageBreakBefore() : null; + if (ct_pageBreak != null + && ct_pageBreak.getVal().intValue() == STOnOff.INT_TRUE) { + return true; } - STBorder.Enum ptrn = ct != null ? ct.getVal() : STBorder.NONE; - return Borders.valueOf(ptrn.intValue()); + return false; } /** @@ -733,29 +856,14 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies that when rendering this document in a paginated - * view, the contents of this paragraph are rendered on the start of a new - * page in the document. - *

    - * If this element is omitted on a given paragraph, - * its value is determined by the setting previously set at any level of the - * style hierarchy (i.e. that previous setting remains unchanged). If this - * setting is never specified in the style hierarchy, then this property - * shall not be applied. Since the paragraph is specified to start on a new - * page, it begins page two even though it could have fit on page one. - *

    + * Specifies the spacing that should be added after the last line in this + * paragraph in the document in absolute units. * - * @return boolean - if page break is set + * @return int - value representing the spacing after the paragraph */ - public boolean isPageBreak() { - CTPPr ppr = getCTPPr(); - CTOnOff ct_pageBreak = ppr.isSetPageBreakBefore() ? ppr - .getPageBreakBefore() : null; - if (ct_pageBreak != null - && ct_pageBreak.getVal().intValue() == STOnOff.INT_TRUE) { - return true; - } - return false; + public int getSpacingAfter() { + CTSpacing spacing = getCTSpacing(false); + return (spacing != null && spacing.isSetAfter()) ? spacing.getAfter().intValue() : -1; } /** @@ -783,11 +891,12 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para * Specifies the spacing that should be added after the last line in this * paragraph in the document in absolute units. * - * @return int - value representing the spacing after the paragraph + * @return bigInteger - value representing the spacing after the paragraph + * @see #setSpacingAfterLines(int) */ - public int getSpacingAfter() { + public int getSpacingAfterLines() { CTSpacing spacing = getCTSpacing(false); - return (spacing != null && spacing.isSetAfter()) ? spacing.getAfter().intValue() : -1; + return (spacing != null && spacing.isSetAfterLines()) ? spacing.getAfterLines().intValue() : -1; } /** @@ -813,20 +922,18 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para spacing.setAfterLines(bi); } - /** - * Specifies the spacing that should be added after the last line in this + * Specifies the spacing that should be added above the first line in this * paragraph in the document in absolute units. * - * @return bigInteger - value representing the spacing after the paragraph - * @see #setSpacingAfterLines(int) + * @return the spacing that should be added above the first line + * @see #setSpacingBefore(int) */ - public int getSpacingAfterLines() { + public int getSpacingBefore() { CTSpacing spacing = getCTSpacing(false); - return (spacing != null && spacing.isSetAfterLines()) ? spacing.getAfterLines().intValue() : -1; + return (spacing != null && spacing.isSetBefore()) ? spacing.getBefore().intValue() : -1; } - /** * Specifies the spacing that should be added above the first line in this * paragraph in the document in absolute units. @@ -844,15 +951,16 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies the spacing that should be added above the first line in this - * paragraph in the document in absolute units. + * Specifies the spacing that should be added before the first line in this paragraph in the + * document in line units. + * The value of this attribute is specified in one hundredths of a line. * - * @return the spacing that should be added above the first line - * @see #setSpacingBefore(int) + * @return the spacing that should be added before the first line in this paragraph + * @see #setSpacingBeforeLines(int) */ - public int getSpacingBefore() { + public int getSpacingBeforeLines() { CTSpacing spacing = getCTSpacing(false); - return (spacing != null && spacing.isSetBefore()) ? spacing.getBefore().intValue() : -1; + return (spacing != null && spacing.isSetBeforeLines()) ? spacing.getBeforeLines().intValue() : -1; } /** @@ -873,33 +981,6 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para spacing.setBeforeLines(bi); } - /** - * Specifies the spacing that should be added before the first line in this paragraph in the - * document in line units. - * The value of this attribute is specified in one hundredths of a line. - * - * @return the spacing that should be added before the first line in this paragraph - * @see #setSpacingBeforeLines(int) - */ - public int getSpacingBeforeLines() { - CTSpacing spacing = getCTSpacing(false); - return (spacing != null && spacing.isSetBeforeLines()) ? spacing.getBeforeLines().intValue() : -1; - } - - - /** - * Specifies how the spacing between lines is calculated as stored in the - * line attribute. If this attribute is omitted, then it shall be assumed to - * be of a value auto if a line attribute value is present. - * - * @param rule - * @see LineSpacingRule - */ - public void setSpacingLineRule(LineSpacingRule rule) { - CTSpacing spacing = getCTSpacing(true); - spacing.setLineRule(STLineSpacingRule.Enum.forInt(rule.getValue())); - } - /** * Specifies how the spacing between lines is calculated as stored in the * line attribute. If this attribute is omitted, then it shall be assumed to @@ -915,24 +996,17 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para .getLineRule().intValue()) : LineSpacingRule.AUTO; } - /** - * Specifies the indentation which shall be placed between the left text - * margin for this paragraph and the left edge of that paragraph's content - * in a left to right paragraph, and the right text margin and the right - * edge of that paragraph's text in a right to left paragraph - *

    - * If this attribute is omitted, its value shall be assumed to be zero. - * Negative values are defined such that the text is moved past the text margin, - * positive values move the text inside the text margin. - *

    + * Specifies how the spacing between lines is calculated as stored in the + * line attribute. If this attribute is omitted, then it shall be assumed to + * be of a value auto if a line attribute value is present. * - * @param indentation + * @param rule + * @see LineSpacingRule */ - public void setIndentationLeft(int indentation) { - CTInd indent = getCTInd(true); - BigInteger bi = new BigInteger("" + indentation); - indent.setLeft(bi); + public void setSpacingLineRule(LineSpacingRule rule) { + CTSpacing spacing = getCTSpacing(true); + spacing.setLineRule(STLineSpacingRule.Enum.forInt(rule.getValue())); } /** @@ -953,10 +1027,10 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para return (indentation != null && indentation.isSetLeft()) ? indentation.getLeft().intValue() : -1; } - + /** - * Specifies the indentation which shall be placed between the right text - * margin for this paragraph and the right edge of that paragraph's content + * Specifies the indentation which shall be placed between the left text + * margin for this paragraph and the left edge of that paragraph's content * in a left to right paragraph, and the right text margin and the right * edge of that paragraph's text in a right to left paragraph *

    @@ -967,10 +1041,10 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para * * @param indentation */ - public void setIndentationRight(int indentation) { + public void setIndentationLeft(int indentation) { CTInd indent = getCTInd(true); BigInteger bi = new BigInteger("" + indentation); - indent.setRight(bi); + indent.setLeft(bi); } /** @@ -994,23 +1068,22 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies the indentation which shall be removed from the first line of - * the parent paragraph, by moving the indentation on the first line back - * towards the beginning of the direction of text flow. - * This indentation is specified relative to the paragraph indentation which is specified for - * all other lines in the parent paragraph. + * Specifies the indentation which shall be placed between the right text + * margin for this paragraph and the right edge of that paragraph's content + * in a left to right paragraph, and the right text margin and the right + * edge of that paragraph's text in a right to left paragraph *

    - * The firstLine and hanging attributes are mutually exclusive, if both are specified, then the - * firstLine value is ignored. + * If this attribute is omitted, its value shall be assumed to be zero. + * Negative values are defined such that the text is moved past the text margin, + * positive values move the text inside the text margin. *

    * * @param indentation */ - - public void setIndentationHanging(int indentation) { + public void setIndentationRight(int indentation) { CTInd indent = getCTInd(true); BigInteger bi = new BigInteger("" + indentation); - indent.setHanging(bi); + indent.setRight(bi); } /** @@ -1032,23 +1105,23 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } /** - * Specifies the additional indentation which shall be applied to the first - * line of the parent paragraph. This additional indentation is specified - * relative to the paragraph indentation which is specified for all other - * lines in the parent paragraph. - * The firstLine and hanging attributes are - * mutually exclusive, if both are specified, then the firstLine value is - * ignored. - * If the firstLineChars attribute is also specified, then this - * value is ignored. If this attribute is omitted, then its value shall be - * assumed to be zero (if needed). + * Specifies the indentation which shall be removed from the first line of + * the parent paragraph, by moving the indentation on the first line back + * towards the beginning of the direction of text flow. + * This indentation is specified relative to the paragraph indentation which is specified for + * all other lines in the parent paragraph. + *

    + * The firstLine and hanging attributes are mutually exclusive, if both are specified, then the + * firstLine value is ignored. + *

    * * @param indentation */ - public void setIndentationFirstLine(int indentation) { + + public void setIndentationHanging(int indentation) { CTInd indent = getCTInd(true); BigInteger bi = new BigInteger("" + indentation); - indent.setFirstLine(bi); + indent.setHanging(bi); } /** @@ -1072,9 +1145,30 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para : -1; } + /** + * Specifies the additional indentation which shall be applied to the first + * line of the parent paragraph. This additional indentation is specified + * relative to the paragraph indentation which is specified for all other + * lines in the parent paragraph. + * The firstLine and hanging attributes are + * mutually exclusive, if both are specified, then the firstLine value is + * ignored. + * If the firstLineChars attribute is also specified, then this + * value is ignored. If this attribute is omitted, then its value shall be + * assumed to be zero (if needed). + * + * @param indentation + */ + public void setIndentationFirstLine(int indentation) { + CTInd indent = getCTInd(true); + BigInteger bi = new BigInteger("" + indentation); + indent.setFirstLine(bi); + } + public int getIndentFromLeft() { return getIndentFromLeft(); } + public void setIndentFromLeft(int dxaLeft) { setIndentationLeft(dxaLeft); } @@ -1082,6 +1176,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para public int getIndentFromRight() { return getIndentFromRight(); } + public void setIndentFromRight(int dxaRight) { setIndentationRight(dxaRight); } @@ -1089,31 +1184,11 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para public int getFirstLineIndent() { return getIndentationFirstLine(); } + public void setFirstLineIndent(int first) { setIndentationFirstLine(first); } - /** - * This element specifies whether a consumer shall break Latin text which - * exceeds the text extents of a line by breaking the word across two lines - * (breaking on the character level) or by moving the word to the following - * line (breaking on the word level). - * - * @param wrap - boolean - */ - public void setWordWrapped(boolean wrap) { - CTOnOff wordWrap = getCTPPr().isSetWordWrap() ? getCTPPr() - .getWordWrap() : getCTPPr().addNewWordWrap(); - if (wrap) - wordWrap.setVal(STOnOff.TRUE); - else - wordWrap.unsetVal(); - } - @Deprecated - public void setWordWrap(boolean wrap) { - setWordWrapped(wrap); - } - /** * This element specifies whether a consumer shall break Latin text which * exceeds the text extents of a line by breaking the word across two lines @@ -1132,13 +1207,46 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } return false; } + + /** + * This element specifies whether a consumer shall break Latin text which + * exceeds the text extents of a line by breaking the word across two lines + * (breaking on the character level) or by moving the word to the following + * line (breaking on the word level). + * + * @param wrap - boolean + */ + public void setWordWrapped(boolean wrap) { + CTOnOff wordWrap = getCTPPr().isSetWordWrap() ? getCTPPr() + .getWordWrap() : getCTPPr().addNewWordWrap(); + if (wrap) + wordWrap.setVal(STOnOff.TRUE); + else + wordWrap.unsetVal(); + } + public boolean isWordWrap() { return isWordWrapped(); } + @Deprecated + public void setWordWrap(boolean wrap) { + setWordWrapped(wrap); + } + + /** + * @return the style of the paragraph + */ + public String getStyle() { + CTPPr pr = getCTPPr(); + CTString style = pr.isSetPStyle() ? pr.getPStyle() : null; + return style != null ? style.getVal() : null; + } + /** * This method provides a style to the paragraph * This is useful when, e.g. an Heading style has to be assigned + * * @param newStyle */ public void setStyle(String newStyle) { @@ -1146,15 +1254,6 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para CTString style = pr.getPStyle() != null ? pr.getPStyle() : pr.addNewPStyle(); style.setVal(newStyle); } - - /** - * @return the style of the paragraph - */ - public String getStyle() { - CTPPr pr = getCTPPr(); - CTString style = pr.isSetPStyle() ? pr.getPStyle() : null; - return style != null ? style.getVal() : null; - } /** * Get a copy of the currently used CTPBrd, if none is used, return @@ -1201,20 +1300,21 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para : paragraph.getPPr(); return pr; } - - + + /** - * add a new run at the end of the position of + * add a new run at the end of the position of * the content of parameter run + * * @param run */ - protected void addRun(CTR run){ + protected void addRun(CTR run) { int pos; pos = paragraph.sizeOfRArray(); paragraph.addNewR(); paragraph.setRArray(pos, run); } - + /** * Appends a new run to this paragraph * @@ -1229,14 +1329,15 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * insert a new Run in RunArray + * * @param pos - * @return the inserted run + * @return the inserted run */ - public XWPFRun insertNewRun(int pos){ + public XWPFRun insertNewRun(int pos) { if (pos >= 0 && pos <= paragraph.sizeOfRArray()) { CTR ctRun = paragraph.insertNewR(pos); XWPFRun newRun = new XWPFRun(ctRun, this); - + // To update the iruns, find where we're going // in the normal runs, and go in there int iPos = iruns.size(); @@ -1248,10 +1349,10 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para } } iruns.add(iPos, newRun); - + // Runs itself is easy to update runs.add(pos, newRun); - + return newRun; } return null; @@ -1261,42 +1362,43 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para * this methods parse the paragraph and search for the string searched. * If it finds the string, it will return true and the position of the String * will be saved in the parameter startPos. + * * @param searched * @param startPos */ - public TextSegement searchText(String searched,PositionInParagraph startPos) { - int startRun = startPos.getRun(), - startText = startPos.getText(), - startChar = startPos.getChar(); + public TextSegement searchText(String searched, PositionInParagraph startPos) { + int startRun = startPos.getRun(), + startText = startPos.getText(), + startChar = startPos.getChar(); int beginRunPos = 0, candCharPos = 0; boolean newList = false; CTR[] rArray = paragraph.getRArray(); - for (int runPos=startRun; runPos=startText){ - String candidate = ((CTText)o).getStringValue(); - if(runPos==startRun) - charPos= startChar; + if (o instanceof CTText) { + if (textPos >= startText) { + String candidate = ((CTText) o).getStringValue(); + if (runPos == startRun) + charPos = startChar; else charPos = 0; - - for(; charPos= 0 && pos < paragraph.sizeOfRArray()) { - getCTP().removeR(pos); + // Remove the run from our high level lists + XWPFRun run = runs.get(pos); runs.remove(pos); + iruns.remove(run); + // Remove the run from the low-level XML + getCTP().removeR(pos); return true; } return false; @@ -1378,23 +1483,24 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * returns the type of the BodyElement Paragraph + * * @see org.apache.poi.xwpf.usermodel.IBodyElement#getElementType() */ public BodyElementType getElementType() { return BodyElementType.PARAGRAPH; } - public IBody getBody() - { + public IBody getBody() { return part; } /** * returns the part of the bodyElement + * * @see org.apache.poi.xwpf.usermodel.IBody#getPart() */ public POIXMLDocumentPart getPart() { - if(part != null){ + if (part != null) { return part.getPart(); } return null; @@ -1402,7 +1508,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * returns the partType of the bodyPart which owns the bodyElement - * + * * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() */ public BodyType getPartType() { @@ -1411,7 +1517,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * adds a new Run to the Paragraph - * + * * @param r */ public void addRun(XWPFRun r) { @@ -1422,7 +1528,7 @@ public class XWPFParagraph implements IBodyElement, IRunBody, ISDTContents, Para /** * return the XWPFRun-Element which owns the CTR run-Element - * + * * @param r */ public XWPFRun getRun(CTR r) { diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java index eba552cc2..c69e8dd1b 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPicture.java @@ -28,51 +28,51 @@ import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture; public class XWPFPicture { private CTPicture ctPic; - private String description; - private XWPFRun run; - - public XWPFPicture(CTPicture ctPic, XWPFRun run){ - this.run = run; - this.ctPic = ctPic; - description = ctPic.getNvPicPr().getCNvPr().getDescr(); + private String description; + private XWPFRun run; + + public XWPFPicture(CTPicture ctPic, XWPFRun run) { + this.run = run; + this.ctPic = ctPic; + description = ctPic.getNvPicPr().getCNvPr().getDescr(); } - - /** - * Link Picture with PictureData - * @param rel - */ - public void setPictureReference(PackageRelationship rel){ - ctPic.getBlipFill().getBlip().setEmbed(rel.getId()); - } - + + /** + * Link Picture with PictureData + * + * @param rel + */ + public void setPictureReference(PackageRelationship rel) { + ctPic.getBlipFill().getBlip().setEmbed(rel.getId()); + } + /** * Return the underlying CTPicture bean that holds all properties for this picture - * - * @return the underlying CTPicture bean - */ - public CTPicture getCTPicture(){ - return ctPic; - } - + * + * @return the underlying CTPicture bean + */ + public CTPicture getCTPicture() { + return ctPic; + } + /** - * Get the PictureData of the Picture, if present. - * Note - not all kinds of picture have data - */ - public XWPFPictureData getPictureData(){ - CTBlipFillProperties blipProps = ctPic.getBlipFill(); - - if(blipProps == null || !blipProps.isSetBlip()) { - // return null if Blip data is missing - return null; - } - - String blipId = blipProps.getBlip().getEmbed(); - POIXMLDocumentPart part = run.getParent().getPart(); - if (part != null) - { - POIXMLDocumentPart relatedPart = part.getRelationById(blipId); - if (relatedPart instanceof XWPFPictureData) { - return (XWPFPictureData) relatedPart; + * Get the PictureData of the Picture, if present. + * Note - not all kinds of picture have data + */ + public XWPFPictureData getPictureData() { + CTBlipFillProperties blipProps = ctPic.getBlipFill(); + + if (blipProps == null || !blipProps.isSetBlip()) { + // return null if Blip data is missing + return null; + } + + String blipId = blipProps.getBlip().getEmbed(); + POIXMLDocumentPart part = run.getParent().getPart(); + if (part != null) { + POIXMLDocumentPart relatedPart = part.getRelationById(blipId); + if (relatedPart instanceof XWPFPictureData) { + return (XWPFPictureData) relatedPart; } } return null; diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java index d7f225358..d685aefca 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java @@ -40,12 +40,13 @@ import org.apache.poi.util.IOUtils; public class XWPFPictureData extends POIXMLDocumentPart { /** - * Relationships for each known picture type - */ - protected static final POIXMLRelation[] RELATIONS; - static { - RELATIONS = new POIXMLRelation[13]; - RELATIONS[Document.PICTURE_TYPE_EMF] = XWPFRelation.IMAGE_EMF; + * Relationships for each known picture type + */ + protected static final POIXMLRelation[] RELATIONS; + + static { + RELATIONS = new POIXMLRelation[13]; + RELATIONS[Document.PICTURE_TYPE_EMF] = XWPFRelation.IMAGE_EMF; RELATIONS[Document.PICTURE_TYPE_WMF] = XWPFRelation.IMAGE_WMF; RELATIONS[Document.PICTURE_TYPE_PICT] = XWPFRelation.IMAGE_PICT; RELATIONS[Document.PICTURE_TYPE_JPEG] = XWPFRelation.IMAGE_JPEG; @@ -59,24 +60,23 @@ public class XWPFPictureData extends POIXMLDocumentPart { } private Long checksum = null; - - /** - * Create a new XWPFGraphicData node - * - */ - protected XWPFPictureData() { - super(); + + /** + * Create a new XWPFGraphicData node + */ + protected XWPFPictureData() { + super(); } /** * Construct XWPFPictureData from a package part - * - * @param part the package part holding the drawing data, - * @param rel the package relationship holding this drawing, - * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/image - */ - public XWPFPictureData(PackagePart part, PackageRelationship rel) { - super(part, rel); + * + * @param part the package part holding the drawing data, + * @param rel the package relationship holding this drawing, + * the relationship type must be http://schemas.openxmlformats.org/officeDocument/2006/relationships/image + */ + public XWPFPictureData(PackagePart part, PackageRelationship rel) { + super(part, rel); } @Override @@ -91,12 +91,13 @@ public class XWPFPictureData extends POIXMLDocumentPart { * You can grab the picture data directly from the underlying package part as follows: *
    * - * InputStream is = getPackagePart().getInputStream(); - * - *

    - * @return the Picture data. - */ - public byte[] getData() { + * InputStream is = getPackagePart().getInputStream(); + * + *

    + * + * @return the Picture data. + */ + public byte[] getData() { try { return IOUtils.toByteArray(getPackagePart().getInputStream()); } catch (IOException e) { @@ -115,21 +116,22 @@ public class XWPFPictureData extends POIXMLDocumentPart { return null; return name.substring(name.lastIndexOf('/') + 1); } - - /** - * Suggests a file extension for this image. - * @return the file extension. - */ - public String suggestFileExtension() { + + /** + * Suggests a file extension for this image. + * + * @return the file extension. + */ + public String suggestFileExtension() { return getPackagePart().getPartName().getExtension(); } - - /** - * Return an integer constant that specifies type of this picture - * - * @return an integer constant that specifies type of this picture - * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF - * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF + + /** + * Return an integer constant that specifies type of this picture + * + * @return an integer constant that specifies type of this picture + * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF + * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PICT * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_JPEG * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PNG @@ -217,13 +219,13 @@ public class XWPFPictureData extends POIXMLDocumentPart { if (!ownPackage.equals(foreignPackage)) { return false; - } - } - } - - Long foreignChecksum = picData.getChecksum(); - Long localChecksum = getChecksum(); - + } + } + } + + Long foreignChecksum = picData.getChecksum(); + Long localChecksum = getChecksum(); + if (!(localChecksum.equals(foreignChecksum))) { return false; } @@ -233,13 +235,13 @@ public class XWPFPictureData extends POIXMLDocumentPart { @Override public int hashCode() { return getChecksum().hashCode(); - } - - /** - * *PictureData objects store the actual content in the part directly without keeping a - * copy like all others therefore we need to handle them differently. - */ - @Override + } + + /** + * *PictureData objects store the actual content in the part directly without keeping a + * copy like all others therefore we need to handle them differently. + */ + @Override protected void prepareForCommit() { // do not clear the part here } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java index 06642faaa..fae051e74 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java @@ -33,7 +33,6 @@ public final class XWPFRelation extends POIXMLRelation { */ protected static final Map _table = new HashMap(); - public static final XWPFRelation DOCUMENT = new XWPFRelation( "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", @@ -41,10 +40,10 @@ public final class XWPFRelation extends POIXMLRelation { null ); public static final XWPFRelation TEMPLATE = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", - "/word/document.xml", - null + "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", + "/word/document.xml", + null ); public static final XWPFRelation MACRO_DOCUMENT = new XWPFRelation( "application/vnd.ms-word.document.macroEnabled.main+xml", @@ -64,12 +63,11 @@ public final class XWPFRelation extends POIXMLRelation { "/word/glossary/document.xml", null ); - public static final XWPFRelation NUMBERING = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", - "/word/numbering.xml", - XWPFNumbering.class + "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", + "/word/numbering.xml", + XWPFNumbering.class ); public static final XWPFRelation FONT_TABLE = new XWPFRelation( "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml", @@ -126,10 +124,10 @@ public final class XWPFRelation extends POIXMLRelation { null ); public static final XWPFRelation FOOTNOTE = new XWPFRelation( - "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes", - "/word/footnotes.xml", - XWPFFootnotes.class + "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes", + "/word/footnotes.xml", + XWPFFootnotes.class ); public static final XWPFRelation ENDNOTE = new XWPFRelation( null, @@ -137,52 +135,51 @@ public final class XWPFRelation extends POIXMLRelation { null, null ); - /** * Supported image formats */ public static final XWPFRelation IMAGE_EMF = new XWPFRelation( - "image/x-emf", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - "/word/media/image#.emf", - XWPFPictureData.class - ); - public static final XWPFRelation IMAGE_WMF = new XWPFRelation( - "image/x-wmf", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - "/word/media/image#.wmf", - XWPFPictureData.class - ); - public static final XWPFRelation IMAGE_PICT = new XWPFRelation( - "image/pict", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - "/word/media/image#.pict", - XWPFPictureData.class - ); - public static final XWPFRelation IMAGE_JPEG = new XWPFRelation( - "image/jpeg", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - "/word/media/image#.jpeg", - XWPFPictureData.class - ); - public static final XWPFRelation IMAGE_PNG = new XWPFRelation( - "image/png", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - "/word/media/image#.png", - XWPFPictureData.class - ); - public static final XWPFRelation IMAGE_DIB = new XWPFRelation( - "image/dib", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - "/word/media/image#.dib", - XWPFPictureData.class - ); - public static final XWPFRelation IMAGE_GIF = new XWPFRelation( - "image/gif", - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - "/word/media/image#.gif", - XWPFPictureData.class - ); + "image/x-emf", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + "/word/media/image#.emf", + XWPFPictureData.class + ); + public static final XWPFRelation IMAGE_WMF = new XWPFRelation( + "image/x-wmf", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + "/word/media/image#.wmf", + XWPFPictureData.class + ); + public static final XWPFRelation IMAGE_PICT = new XWPFRelation( + "image/pict", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + "/word/media/image#.pict", + XWPFPictureData.class + ); + public static final XWPFRelation IMAGE_JPEG = new XWPFRelation( + "image/jpeg", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + "/word/media/image#.jpeg", + XWPFPictureData.class + ); + public static final XWPFRelation IMAGE_PNG = new XWPFRelation( + "image/png", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + "/word/media/image#.png", + XWPFPictureData.class + ); + public static final XWPFRelation IMAGE_DIB = new XWPFRelation( + "image/dib", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + "/word/media/image#.dib", + XWPFPictureData.class + ); + public static final XWPFRelation IMAGE_GIF = new XWPFRelation( + "image/gif", + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + "/word/media/image#.gif", + XWPFPictureData.class + ); public static final XWPFRelation IMAGE_TIFF = new XWPFRelation( "image/tiff", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", @@ -207,14 +204,12 @@ public final class XWPFRelation extends POIXMLRelation { "/word/media/image#.wpg", XWPFPictureData.class ); - - public static final XWPFRelation IMAGES = new XWPFRelation( - null, - "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", - null, - null - ); - + public static final XWPFRelation IMAGES = new XWPFRelation( + null, + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", + null, + null + ); private XWPFRelation(String type, String rel, String defaultName, Class cls) { super(type, rel, defaultName, cls); diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRun.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRun.java index 07debb98c..1c14bb274 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRun.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRun.java @@ -32,19 +32,52 @@ import org.apache.poi.wp.usermodel.CharacterRun; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; -import org.apache.xmlbeans.XmlString; -import org.apache.xmlbeans.XmlToken; -import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl; -import org.openxmlformats.schemas.drawingml.x2006.main.*; -import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture; -import org.openxmlformats.schemas.drawingml.x2006.picture.CTPictureNonVisual; -import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor; -import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTColor; -import org.w3c.dom.NodeList; -import org.w3c.dom.Text; - +import org.apache.xmlbeans.XmlString; +import org.apache.xmlbeans.XmlToken; +import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualPictureProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D; +import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; +import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture; +import org.openxmlformats.schemas.drawingml.x2006.picture.CTPictureNonVisual; +import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor; +import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTColor; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTEmpty; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFFCheckBox; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFldChar; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdnRef; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHpsMeasure; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPTab; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSignedHpsMeasure; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSignedTwipsMeasure; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTUnderline; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalAlignRun; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBrClear; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBrType; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFldCharType; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STUnderline; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalAlignRun; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + /** * XWPFRun object defines a region of text with a common set of properties */ @@ -52,22 +85,12 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { private CTR run; private String pictureText; private IRunBody parent; - private List pictures; - - /** - * @see [MS-OI29500] Run Fonts - */ - public static enum FontCharRange { - ascii /* char 0-127 */, - cs /* complex symbol */, - eastAsia /* east asia */, - hAnsi /* high ansi */ - }; - - /** - * @param r the CTR bean which holds the run attributes - * @param p the parent paragraph - */ + private List pictures; + + /** + * @param r the CTR bean which holds the run attributes + * @param p the parent paragraph + */ @SuppressWarnings("deprecation") public XWPFRun(CTR r, IRunBody p) { this.run = r; @@ -92,13 +115,13 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { // Look for any text in any of our pictures or drawings StringBuilder text = new StringBuilder(); - List pictTextObjs = new ArrayList(); - pictTextObjs.addAll(Arrays.asList(r.getPictArray())); - pictTextObjs.addAll(Arrays.asList(r.getDrawingArray())); - for(XmlObject o : pictTextObjs) { - XmlObject[] ts = o.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//w:t"); - for (XmlObject t : ts) { - NodeList kids = t.getDomNode().getChildNodes(); + List pictTextObjs = new ArrayList(); + pictTextObjs.addAll(Arrays.asList(r.getPictArray())); + pictTextObjs.addAll(Arrays.asList(r.getDrawingArray())); + for (XmlObject o : pictTextObjs) { + XmlObject[] ts = o.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//w:t"); + for (XmlObject t : ts) { + NodeList kids = t.getDomNode().getChildNodes(); for (int n = 0; n < kids.getLength(); n++) { if (kids.item(n) instanceof Text) { if (text.length() > 0) @@ -110,112 +133,134 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { } pictureText = text.toString(); - // Do we have any embedded pictures? - // (They're a different CTPicture, under the drawingml namespace) - pictures = new ArrayList(); - for(XmlObject o : pictTextObjs) { - for(CTPicture pict : getCTPictures(o)) { - XWPFPicture picture = new XWPFPicture(pict, this); - pictures.add(picture); - } - } + // Do we have any embedded pictures? + // (They're a different CTPicture, under the drawingml namespace) + pictures = new ArrayList(); + for (XmlObject o : pictTextObjs) { + for (CTPicture pict : getCTPictures(o)) { + XWPFPicture picture = new XWPFPicture(pict, this); + pictures.add(picture); + } + } + } + + ; + + /** + * @deprecated Use {@link XWPFRun#XWPFRun(CTR, IRunBody)} + */ + public XWPFRun(CTR r, XWPFParagraph p) { + this(r, (IRunBody) p); + } + + /** + * Add the xml:spaces="preserve" attribute if the string has leading or trailing white spaces + * + * @param xs the string to check + */ + static void preserveSpaces(XmlString xs) { + String text = xs.getStringValue(); + if (text != null && (text.startsWith(" ") || text.endsWith(" "))) { + XmlCursor c = xs.newCursor(); + c.toNextToken(); + c.insertAttributeWithValue(new QName("http://www.w3.org/XML/1998/namespace", "space"), "preserve"); + c.dispose(); + } + } + + private List getCTPictures(XmlObject o) { + List pictures = new ArrayList(); + XmlObject[] picts = o.selectPath("declare namespace pic='" + CTPicture.type.getName().getNamespaceURI() + "' .//pic:pic"); + for (XmlObject pict : picts) { + if (pict instanceof XmlAnyTypeImpl) { + // Pesky XmlBeans bug - see Bugzilla #49934 + try { + pict = CTPicture.Factory.parse(pict.toString()); + } catch (XmlException e) { + throw new POIXMLException(e); + } + } + if (pict instanceof CTPicture) { + pictures.add((CTPicture) pict); + } + } + return pictures; } - /** - * @deprecated Use {@link XWPFRun#XWPFRun(CTR, IRunBody)} - */ - public XWPFRun(CTR r, XWPFParagraph p) { - this(r, (IRunBody)p); - } - - private List getCTPictures(XmlObject o) { - List pictures = new ArrayList(); - XmlObject[] picts = o.selectPath("declare namespace pic='"+CTPicture.type.getName().getNamespaceURI()+"' .//pic:pic"); - for(XmlObject pict : picts) { - if(pict instanceof XmlAnyTypeImpl) { - // Pesky XmlBeans bug - see Bugzilla #49934 - try { - pict = CTPicture.Factory.parse( pict.toString() ); - } catch(XmlException e) { - throw new POIXMLException(e); - } - } - if(pict instanceof CTPicture) { - pictures.add((CTPicture)pict); - } - } - return pictures; - } - - /** - * Get the currently used CTR object - * @return ctr object - */ - @Internal + + /** + * Get the currently used CTR object + * + * @return ctr object + */ + @Internal public CTR getCTR() { return run; } - - /** - * Get the currently referenced paragraph/SDT object - * @return current parent - */ - public IRunBody getParent() { - return parent; - } - /** - * Get the currently referenced paragraph, or null if a SDT object - * @deprecated use {@link XWPFRun#getParent()} instead - */ - public XWPFParagraph getParagraph() { - if (parent instanceof XWPFParagraph) - return (XWPFParagraph)parent; - return null; - } - - /** - * @return The {@link XWPFDocument} instance, this run belongs to, or - * null if parent structure (paragraph > document) is not properly set. - */ - public XWPFDocument getDocument() { - if (parent != null) { + + /** + * Get the currently referenced paragraph/SDT object + * + * @return current parent + */ + public IRunBody getParent() { + return parent; + } + + /** + * Get the currently referenced paragraph, or null if a SDT object + * + * @deprecated use {@link XWPFRun#getParent()} instead + */ + public XWPFParagraph getParagraph() { + if (parent instanceof XWPFParagraph) + return (XWPFParagraph) parent; + return null; + } + + /** + * @return The {@link XWPFDocument} instance, this run belongs to, or + * null if parent structure (paragraph > document) is not properly set. + */ + public XWPFDocument getDocument() { + if (parent != null) { return parent.getDocument(); } return null; } /** - * For isBold, isItalic etc - */ - private boolean isCTOnOff(CTOnOff onoff) { - if(! onoff.isSetVal()) - return true; - if(onoff.getVal() == STOnOff.ON) - return true; - if(onoff.getVal() == STOnOff.TRUE) - return true; - return false; - } + * For isBold, isItalic etc + */ + private boolean isCTOnOff(CTOnOff onoff) { + if (!onoff.isSetVal()) + return true; + if (onoff.getVal() == STOnOff.ON) + return true; + if (onoff.getVal() == STOnOff.TRUE) + return true; + return false; + } /** * Whether the bold property shall be applied to all non-complex script * characters in the contents of this run when displayed in a document * * @return true if the bold property is applied - */ - public boolean isBold() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetB()) { - return false; - } - return isCTOnOff(pr.getB()); + */ + public boolean isBold() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetB()) { + return false; + } + return isCTOnOff(pr.getB()); } - - /** - * Whether the bold property shall be applied to all non-complex script - * characters in the contents of this run when displayed in a document. - *

    - * This formatting property is a toggle property, which specifies that its - * behavior differs between its use within a style definition and its use as + + /** + * Whether the bold property shall be applied to all non-complex script + * characters in the contents of this run when displayed in a document. + *

    + * This formatting property is a toggle property, which specifies that its + * behavior differs between its use within a style definition and its use as * direct formatting. When used as part of a style definition, setting this * property shall toggle the current state of that property as specified up * to this point in the hierarchy (i.e. applied to not applied, and vice @@ -241,25 +286,26 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { } /** - * Get text color. The returned value is a string in the hex form "RRGGBB". - */ - public String getColor() { - String color = null; - if (run.isSetRPr()) { - CTRPr pr = run.getRPr(); - if (pr.isSetColor()) { - CTColor clr = pr.getColor(); - color = clr.xgetVal().getStringValue(); - } - } - return color; - } - - /** - * Set text color. - * @param rgbStr - the desired color, in the hex form "RRGGBB". - */ - public void setColor(String rgbStr) { + * Get text color. The returned value is a string in the hex form "RRGGBB". + */ + public String getColor() { + String color = null; + if (run.isSetRPr()) { + CTRPr pr = run.getRPr(); + if (pr.isSetColor()) { + CTColor clr = pr.getColor(); + color = clr.xgetVal().getStringValue(); + } + } + return color; + } + + /** + * Set text color. + * + * @param rgbStr - the desired color, in the hex form "RRGGBB". + */ + public void setColor(String rgbStr) { CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); CTColor color = pr.isSetColor() ? pr.getColor() : pr.addNewColor(); color.setVal(rgbStr); @@ -285,23 +331,24 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { /** * Sets the text of this text run * - * @param value the literal text which shall be displayed in the document - */ - public void setText(String value) { - setText(value,run.sizeOfTArray()); - } - - /** - * Sets the text of this text run in the - * - * @param value the literal text which shall be displayed in the document - * @param pos - position in the text array (NB: 0 based) - */ - public void setText(String value, int pos) { - if(pos > run.sizeOfTArray()) throw new ArrayIndexOutOfBoundsException("Value too large for the parameter position in XWPFRun.setText(String value,int pos)"); - CTText t = (pos < run.sizeOfTArray() && pos >= 0) ? run.getTArray(pos) : run.addNewT(); - t.setStringValue(value); - preserveSpaces(t); + * @param value the literal text which shall be displayed in the document + */ + public void setText(String value) { + setText(value, run.sizeOfTArray()); + } + + /** + * Sets the text of this text run in the + * + * @param value the literal text which shall be displayed in the document + * @param pos - position in the text array (NB: 0 based) + */ + public void setText(String value, int pos) { + if (pos > run.sizeOfTArray()) + throw new ArrayIndexOutOfBoundsException("Value too large for the parameter position in XWPFRun.setText(String value,int pos)"); + CTText t = (pos < run.sizeOfTArray() && pos >= 0) ? run.getTArray(pos) : run.addNewT(); + t.setStringValue(value); + preserveSpaces(t); } /** @@ -309,13 +356,13 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { * characters in the contents of this run when displayed in a document. * * @return true if the italic property is applied - */ - public boolean isItalic() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetI()) - return false; - return isCTOnOff(pr.getI()); - } + */ + public boolean isItalic() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetI()) + return false; + return isCTOnOff(pr.getI()); + } /** * Whether the bold property shall be applied to all non-complex script @@ -354,14 +401,14 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { * * @return the Underline pattern applyed to this run * @see UnderlinePatterns - */ - public UnderlinePatterns getUnderline() { - CTRPr pr = run.getRPr(); - return (pr != null && pr.isSetU() && pr.getU().getVal() != null) - ? UnderlinePatterns.valueOf(pr.getU().getVal().intValue()) - : UnderlinePatterns.NONE; - } - + */ + public UnderlinePatterns getUnderline() { + CTRPr pr = run.getRPr(); + return (pr != null && pr.isSetU() && pr.getU().getVal() != null) + ? UnderlinePatterns.valueOf(pr.getU().getVal().intValue()) + : UnderlinePatterns.NONE; + } + /** * Specifies that the contents of this run should be displayed along with an * underline appearing directly below the character heigh @@ -388,32 +435,16 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { * horizontal line through the center of the line. * * @return true if the strike property is applied - */ - public boolean isStrikeThrough() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetStrike()) - return false; - return isCTOnOff(pr.getStrike()); - } - @Deprecated - public boolean isStrike() { - return isStrikeThrough(); - } - /** - * Specifies that the contents of this run shall be displayed with a double - * horizontal line through the center of the line. - * - * @return true if the double strike property is applied - */ - public boolean isDoubleStrikeThrough() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetDstrike()) - return false; - return isCTOnOff(pr.getDstrike()); - } - - /** - * Specifies that the contents of this run shall be displayed with a single + */ + public boolean isStrikeThrough() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetStrike()) + return false; + return isCTOnOff(pr.getStrike()); + } + + /** + * Specifies that the contents of this run shall be displayed with a single * horizontal line through the center of the line. *

    * This formatting property is a toggle property, which specifies that its @@ -438,86 +469,113 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { */ public void setStrikeThrough(boolean value) { CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTOnOff strike = pr.isSetStrike() ? pr.getStrike() : pr.addNewStrike(); - strike.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); - } - @Deprecated - public void setStrike(boolean value) { - setStrikeThrough(value); - } - /** - * Specifies that the contents of this run shall be displayed with a - * double horizontal line through the center of the line. - * @see #setStrikeThrough(boolean) for the rules about this - */ - public void setDoubleStrikethrough(boolean value) { + CTOnOff strike = pr.isSetStrike() ? pr.getStrike() : pr.addNewStrike(); + strike.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); + } + + @Deprecated + public boolean isStrike() { + return isStrikeThrough(); + } + + @Deprecated + public void setStrike(boolean value) { + setStrikeThrough(value); + } + + /** + * Specifies that the contents of this run shall be displayed with a double + * horizontal line through the center of the line. + * + * @return true if the double strike property is applied + */ + public boolean isDoubleStrikeThrough() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetDstrike()) + return false; + return isCTOnOff(pr.getDstrike()); + } + + /** + * Specifies that the contents of this run shall be displayed with a + * double horizontal line through the center of the line. + * + * @see #setStrikeThrough(boolean) for the rules about this + */ + public void setDoubleStrikethrough(boolean value) { CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); CTOnOff dstrike = pr.isSetDstrike() ? pr.getDstrike() : pr.addNewDstrike(); dstrike.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); } - - public boolean isSmallCaps() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetSmallCaps()) - return false; - return isCTOnOff(pr.getSmallCaps()); - } - public void setSmallCaps(boolean value) { - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTOnOff caps = pr.isSetSmallCaps() ? pr.getSmallCaps() : pr.addNewSmallCaps(); - caps.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); - } - public boolean isCapitalized() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetCaps()) - return false; - return isCTOnOff(pr.getCaps()); - } - public void setCapitalized(boolean value) { - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTOnOff caps = pr.isSetCaps() ? pr.getCaps() : pr.addNewCaps(); - caps.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); - } - - public boolean isShadowed() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetShadow()) - return false; - return isCTOnOff(pr.getShadow()); - } - public void setShadow(boolean value) { - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTOnOff shadow = pr.isSetShadow() ? pr.getShadow() : pr.addNewShadow(); - shadow.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); - } - - public boolean isImprinted() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetImprint()) - return false; - return isCTOnOff(pr.getImprint()); - } - public void setImprinted(boolean value) { - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTOnOff imprinted = pr.isSetImprint() ? pr.getImprint() : pr.addNewImprint(); - imprinted.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); - } - - public boolean isEmbossed() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetEmboss()) - return false; - return isCTOnOff(pr.getEmboss()); - } - public void setEmbossed(boolean value) { - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTOnOff emboss = pr.isSetEmboss() ? pr.getEmboss() : pr.addNewEmboss(); - emboss.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); - } - - /** - * Specifies the alignment which shall be applied to the contents of this - * run in relation to the default appearance of the run's text. + + public boolean isSmallCaps() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetSmallCaps()) + return false; + return isCTOnOff(pr.getSmallCaps()); + } + + public void setSmallCaps(boolean value) { + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTOnOff caps = pr.isSetSmallCaps() ? pr.getSmallCaps() : pr.addNewSmallCaps(); + caps.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); + } + + public boolean isCapitalized() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetCaps()) + return false; + return isCTOnOff(pr.getCaps()); + } + + public void setCapitalized(boolean value) { + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTOnOff caps = pr.isSetCaps() ? pr.getCaps() : pr.addNewCaps(); + caps.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); + } + + public boolean isShadowed() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetShadow()) + return false; + return isCTOnOff(pr.getShadow()); + } + + public void setShadow(boolean value) { + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTOnOff shadow = pr.isSetShadow() ? pr.getShadow() : pr.addNewShadow(); + shadow.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); + } + + public boolean isImprinted() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetImprint()) + return false; + return isCTOnOff(pr.getImprint()); + } + + public void setImprinted(boolean value) { + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTOnOff imprinted = pr.isSetImprint() ? pr.getImprint() : pr.addNewImprint(); + imprinted.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); + } + + public boolean isEmbossed() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetEmboss()) + return false; + return isCTOnOff(pr.getEmboss()); + } + + public void setEmbossed(boolean value) { + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTOnOff emboss = pr.isSetEmboss() ? pr.getEmboss() : pr.addNewEmboss(); + emboss.setVal(value ? STOnOff.TRUE : STOnOff.FALSE); + } + + /** + * Specifies the alignment which shall be applied to the contents of this + * run in relation to the default appearance of the run's text. * This allows the text to be repositioned as subscript or superscript without * altering the font size of the run properties. * @@ -550,105 +608,106 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { CTVerticalAlignRun ctValign = pr.isSetVertAlign() ? pr.getVertAlign() : pr.addNewVertAlign(); ctValign.setVal(STVerticalAlignRun.Enum.forInt(valign.getValue())); } - - public int getKerning() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetKern()) - return 0; - return pr.getKern().getVal().intValue(); - } - public void setKerning(int kern) { - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTHpsMeasure kernmes = pr.isSetKern() ? pr.getKern() : pr.addNewKern(); - kernmes.setVal(BigInteger.valueOf(kern)); - } - - public int getCharacterSpacing() { - CTRPr pr = run.getRPr(); - if(pr == null || !pr.isSetSpacing()) - return 0; - return pr.getSpacing().getVal().intValue(); - } - public void setCharacterSpacing(int twips) { - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTSignedTwipsMeasure spc = pr.isSetSpacing() ? pr.getSpacing() : pr.addNewSpacing(); - spc.setVal(BigInteger.valueOf(twips)); - } - - /** - * Gets the fonts which shall be used to display the text contents of - * this run. Specifies a font which shall be used to format all characters + + public int getKerning() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetKern()) + return 0; + return pr.getKern().getVal().intValue(); + } + + public void setKerning(int kern) { + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTHpsMeasure kernmes = pr.isSetKern() ? pr.getKern() : pr.addNewKern(); + kernmes.setVal(BigInteger.valueOf(kern)); + } + + public int getCharacterSpacing() { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetSpacing()) + return 0; + return pr.getSpacing().getVal().intValue(); + } + + public void setCharacterSpacing(int twips) { + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTSignedTwipsMeasure spc = pr.isSetSpacing() ? pr.getSpacing() : pr.addNewSpacing(); + spc.setVal(BigInteger.valueOf(twips)); + } + + /** + * Gets the fonts which shall be used to display the text contents of + * this run. Specifies a font which shall be used to format all characters * in the ASCII range (0 - 127) within the parent run * * @return a string representing the font family */ - public String getFontFamily() { - return getFontFamily(null); - } - /** - * Alias for {@link #getFontFamily()} - */ - public String getFontName() { + public String getFontFamily() { + return getFontFamily(null); + } + + /** + * Specifies the fonts which shall be used to display the text contents of + * this run. Specifies a font which shall be used to format all characters + * in the ASCII range (0 - 127) within the parent run. + *

    + * Also sets the other font ranges, if they haven't been set before + * + * @param fontFamily + * @see FontCharRange + */ + public void setFontFamily(String fontFamily) { + setFontFamily(fontFamily, null); + } + + /** + * Alias for {@link #getFontFamily()} + */ + public String getFontName() { return getFontFamily(); } /** * Gets the font family for the specified font char range. - * If fcr is null, the font char range "ascii" is used - * - * @param fcr the font char range, defaults to "ansi" - * @return a string representing the font famil - */ - public String getFontFamily(FontCharRange fcr) { - CTRPr pr = run.getRPr(); - if (pr == null || !pr.isSetRFonts()) return null; - - CTFonts fonts = pr.getRFonts(); - switch (fcr == null ? FontCharRange.ascii : fcr) { - default: - case ascii: - return fonts.getAscii(); - case cs: - return fonts.getCs(); - case eastAsia: - return fonts.getEastAsia(); - case hAnsi: - return fonts.getHAnsi(); - } - } - - - /** - * Specifies the fonts which shall be used to display the text contents of - * this run. Specifies a font which shall be used to format all characters - * in the ASCII range (0 - 127) within the parent run. - * - * Also sets the other font ranges, if they haven't been set before - * - * @param fontFamily - * - * @see FontCharRange - */ - public void setFontFamily(String fontFamily) { - setFontFamily(fontFamily, null); - } - - /** - * Specifies the fonts which shall be used to display the text contents of - * this run. The default handling for fcr == null is to overwrite the - * ascii font char range with the given font family and also set all not - * specified font ranges - * - * @param fontFamily - * @param fcr FontCharRange or null for default handling - */ - public void setFontFamily(String fontFamily, FontCharRange fcr) { - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTFonts fonts = pr.isSetRFonts() ? pr.getRFonts() : pr.addNewRFonts(); - - if (fcr == null) { - fonts.setAscii(fontFamily); - if (!fonts.isSetHAnsi()) { + * If fcr is null, the font char range "ascii" is used + * + * @param fcr the font char range, defaults to "ansi" + * @return a string representing the font famil + */ + public String getFontFamily(FontCharRange fcr) { + CTRPr pr = run.getRPr(); + if (pr == null || !pr.isSetRFonts()) return null; + + CTFonts fonts = pr.getRFonts(); + switch (fcr == null ? FontCharRange.ascii : fcr) { + default: + case ascii: + return fonts.getAscii(); + case cs: + return fonts.getCs(); + case eastAsia: + return fonts.getEastAsia(); + case hAnsi: + return fonts.getHAnsi(); + } + } + + /** + * Specifies the fonts which shall be used to display the text contents of + * this run. The default handling for fcr == null is to overwrite the + * ascii font char range with the given font family and also set all not + * specified font ranges + * + * @param fontFamily + * @param fcr FontCharRange or null for default handling + */ + public void setFontFamily(String fontFamily, FontCharRange fcr) { + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTFonts fonts = pr.isSetRFonts() ? pr.getRFonts() : pr.addNewRFonts(); + + if (fcr == null) { + fonts.setAscii(fontFamily); + if (!fonts.isSetHAnsi()) { fonts.setHAnsi(fontFamily); } if (!fonts.isSetCs()) { @@ -656,24 +715,24 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { } if (!fonts.isSetEastAsia()) { fonts.setEastAsia(fontFamily); - } - } else { - switch (fcr) { - case ascii: - fonts.setAscii(fontFamily); - break; - case cs: - fonts.setCs(fontFamily); - break; - case eastAsia: - fonts.setEastAsia(fontFamily); - break; - case hAnsi: - fonts.setHAnsi(fontFamily); - break; - } - } - } + } + } else { + switch (fcr) { + case ascii: + fonts.setAscii(fontFamily); + break; + case cs: + fonts.setCs(fontFamily); + break; + case eastAsia: + fonts.setEastAsia(fontFamily); + break; + case hAnsi: + fonts.setHAnsi(fontFamily); + break; + } + } + } /** * Specifies the font size which shall be applied to all non complex script @@ -696,13 +755,13 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { * be used for non complex script characters. *

    * - * @param size - */ - public void setFontSize(int size) { - BigInteger bint=new BigInteger(""+size); - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTHpsMeasure ctSize = pr.isSetSz() ? pr.getSz() : pr.addNewSz(); - ctSize.setVal(bint.multiply(new BigInteger("2"))); + * @param size + */ + public void setFontSize(int size) { + BigInteger bint = new BigInteger("" + size); + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTHpsMeasure ctSize = pr.isSetSz() ? pr.getSz() : pr.addNewSz(); + ctSize.setVal(bint.multiply(new BigInteger("2"))); } /** @@ -739,52 +798,54 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { * contents of this run. *

    * - * @param val - */ - public void setTextPosition(int val) { - BigInteger bint=new BigInteger(""+val); - CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); - CTSignedHpsMeasure position = pr.isSetPosition() ? pr.getPosition() : pr.addNewPosition(); - position.setVal(bint); + * @param val + */ + public void setTextPosition(int val) { + BigInteger bint = new BigInteger("" + val); + CTRPr pr = run.isSetRPr() ? run.getRPr() : run.addNewRPr(); + CTSignedHpsMeasure position = pr.isSetPosition() ? pr.getPosition() : pr.addNewPosition(); + position.setVal(bint); + } + + /** + * + */ + public void removeBreak() { + // TODO } - - /** - * - */ - public void removeBreak() { - // TODO - } - - /** - * Specifies that a break shall be placed at the current location in the run - * content. - * A break is a special character which is used to override the - * normal line breaking that would be performed based on the normal layout - * of the document's contents. - * @see #addCarriageReturn() - */ - public void addBreak() { - run.addNewBr(); - } - - /** - * Specifies that a break shall be placed at the current location in the run + + /** + * Specifies that a break shall be placed at the current location in the run + * content. + * A break is a special character which is used to override the + * normal line breaking that would be performed based on the normal layout + * of the document's contents. + * + * @see #addCarriageReturn() + */ + public void addBreak() { + run.addNewBr(); + } + + /** + * Specifies that a break shall be placed at the current location in the run * content. * A break is a special character which is used to override the * normal line breaking that would be performed based on the normal layout * of the document's contents. *

    * The behavior of this break character (the - * location where text shall be restarted after this break) shall be - * determined by its type values. - *

    - * @see BreakType - */ - public void addBreak(BreakType type){ - CTBr br=run.addNewBr(); - br.setType(STBrType.Enum.forInt(type.getValue())); - } - + * location where text shall be restarted after this break) shall be + * determined by its type values. + *

    + * + * @see BreakType + */ + public void addBreak(BreakType type) { + CTBr br = run.addNewBr(); + br.setType(STBrType.Enum.forInt(type.getValue())); + } + /** * Specifies that a break shall be placed at the current location in the run * content. A break is a special character which is used to override the @@ -792,31 +853,32 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { * of the document's contents. *

    * The behavior of this break character (the - * location where text shall be restarted after this break) shall be - * determined by its type (in this case is BreakType.TEXT_WRAPPING as default) and clear attribute values. - *

    - * @see BreakClear - */ - public void addBreak(BreakClear clear){ - CTBr br=run.addNewBr(); - br.setType(STBrType.Enum.forInt(BreakType.TEXT_WRAPPING.getValue())); - br.setClear(STBrClear.Enum.forInt(clear.getValue())); + * location where text shall be restarted after this break) shall be + * determined by its type (in this case is BreakType.TEXT_WRAPPING as default) and clear attribute values. + *

    + * + * @see BreakClear + */ + public void addBreak(BreakClear clear) { + CTBr br = run.addNewBr(); + br.setType(STBrType.Enum.forInt(BreakType.TEXT_WRAPPING.getValue())); + br.setClear(STBrClear.Enum.forInt(clear.getValue())); + } + + /** + * Specifies that a tab shall be placed at the current location in + * the run content. + */ + public void addTab() { + run.addNewTab(); } - - /** - * Specifies that a tab shall be placed at the current location in - * the run content. - */ - public void addTab() { - run.addNewTab(); - } - - public void removeTab() { - //TODO - } - - /** - * Specifies that a carriage return shall be placed at the + + public void removeTab() { + //TODO + } + + /** + * Specifies that a carriage return shall be placed at the * current location in the run content. * A carriage return is used to end the current line of text in * Wordprocess. @@ -830,34 +892,33 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { public void addCarriageReturn() { run.addNewCr(); } - - public void removeCarriageReturn() { - //TODO - } - - /** - * Adds a picture to the run. This method handles - * attaching the picture data to the overall file. - * - * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF - * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF - * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PICT - * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_JPEG - * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PNG - * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB - * - * @param pictureData The raw picture data - * @param pictureType The type of the picture, eg {@link Document#PICTURE_TYPE_JPEG} - * @param width width in EMUs. To convert to / from points use {@link org.apache.poi.util.Units} - * @param height height in EMUs. To convert to / from points use {@link org.apache.poi.util.Units} - * @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException - * @throws IOException - */ - public XWPFPicture addPicture(InputStream pictureData, int pictureType, String filename, int width, int height) - throws InvalidFormatException, IOException { - XWPFDocument doc = parent.getDocument(); - - // Add the picture + relationship + + public void removeCarriageReturn() { + //TODO + } + + /** + * Adds a picture to the run. This method handles + * attaching the picture data to the overall file. + * + * @param pictureData The raw picture data + * @param pictureType The type of the picture, eg {@link Document#PICTURE_TYPE_JPEG} + * @param width width in EMUs. To convert to / from points use {@link org.apache.poi.util.Units} + * @param height height in EMUs. To convert to / from points use {@link org.apache.poi.util.Units} + * @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException + * @throws IOException + * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF + * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF + * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PICT + * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_JPEG + * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PNG + * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB + */ + public XWPFPicture addPicture(InputStream pictureData, int pictureType, String filename, int width, int height) + throws InvalidFormatException, IOException { + XWPFDocument doc = parent.getDocument(); + + // Add the picture + relationship String relationId = doc.addPictureData(pictureData, pictureType); XWPFPictureData picData = (XWPFPictureData) doc.getRelationById(relationId); @@ -865,18 +926,18 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { try { CTDrawing drawing = run.addNewDrawing(); CTInline inline = drawing.addNewInline(); - - // Do the fiddly namespace bits on the inline - // (We need full control of what goes where and as what) - String xml = - "" + - "" + - "" + - "" + - ""; - inline.set(XmlToken.Factory.parse(xml)); - - // Setup the inline + + // Do the fiddly namespace bits on the inline + // (We need full control of what goes where and as what) + String xml = + "" + + "" + + "" + + "" + + ""; + inline.set(XmlToken.Factory.parse(xml)); + + // Setup the inline inline.setDistT(0); inline.setDistR(0); inline.setDistB(0); @@ -910,13 +971,13 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { CTNonVisualPictureProperties cNvPicPr = nvPicPr.addNewCNvPicPr(); cNvPicPr.addNewPicLocks().setNoChangeAspect(true); - - CTBlipFillProperties blipFill = pic.addNewBlipFill(); - CTBlip blip = blipFill.addNewBlip(); - blip.setEmbed( picData.getPackageRelationship().getId() ); - blipFill.addNewStretch().addNewFillRect(); - - CTShapeProperties spPr = pic.addNewSpPr(); + + CTBlipFillProperties blipFill = pic.addNewBlipFill(); + CTBlip blip = blipFill.addNewBlip(); + blip.setEmbed(picData.getPackageRelationship().getId()); + blipFill.addNewStretch().addNewFillRect(); + + CTShapeProperties spPr = pic.addNewSpPr(); CTTransform2D xfrm = spPr.addNewXfrm(); CTPoint2D off = xfrm.addNewOff(); @@ -932,50 +993,36 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { prstGeom.addNewAvLst(); // Finish up - XWPFPicture xwpfPicture = new XWPFPicture(pic, this); - pictures.add(xwpfPicture); - return xwpfPicture; - } catch(XmlException e) { - throw new IllegalStateException(e); - } - } - - /** - * Returns the embedded pictures of the run. These - * are pictures which reference an external, - * embedded picture image such as a .png or .jpg - */ - public List getEmbeddedPictures() { - return pictures; - } - - /** - * Add the xml:spaces="preserve" attribute if the string has leading or trailing white spaces - * - * @param xs the string to check - */ - static void preserveSpaces(XmlString xs) { - String text = xs.getStringValue(); - if (text != null && (text.startsWith(" ") || text.endsWith(" "))) { - XmlCursor c = xs.newCursor(); - c.toNextToken(); - c.insertAttributeWithValue(new QName("http://www.w3.org/XML/1998/namespace", "space"), "preserve"); - c.dispose(); - } - } - - /** - * Returns the string version of the text - */ - public String toString() { - return text(); - } - /** - * Returns the string version of the text, with tabs and - * carriage returns in place of their xml equivalents. - */ - public String text() { - StringBuffer text = new StringBuffer(); + XWPFPicture xwpfPicture = new XWPFPicture(pic, this); + pictures.add(xwpfPicture); + return xwpfPicture; + } catch (XmlException e) { + throw new IllegalStateException(e); + } + } + + /** + * Returns the embedded pictures of the run. These + * are pictures which reference an external, + * embedded picture image such as a .png or .jpg + */ + public List getEmbeddedPictures() { + return pictures; + } + + /** + * Returns the string version of the text + */ + public String toString() { + return text(); + } + + /** + * Returns the string version of the text, with tabs and + * carriage returns in place of their xml equivalents. + */ + public String text() { + StringBuffer text = new StringBuffer(); // Grab the text and tabs of the text run // Do so in a way that preserves the ordering @@ -989,26 +1036,26 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { // come up as instances of CTText, but we don't want them // in the normal text output if (!"w:instrText".equals(tagName)) { - text.append(((CTText) o).getStringValue()); - } - } - - // Complex type evaluation (currently only for extraction of check boxes) - if(o instanceof CTFldChar) { - CTFldChar ctfldChar = ((CTFldChar)o); - if(ctfldChar.getFldCharType() == STFldCharType.BEGIN) { - if(ctfldChar.getFfData() != null) { - for(CTFFCheckBox checkBox : ctfldChar.getFfData().getCheckBoxList()) { - if(checkBox.getDefault().getVal() == STOnOff.X_1) { - text.append("|X|"); - } else { - text.append("|_|"); - } - } - } - } - } - + text.append(((CTText) o).getStringValue()); + } + } + + // Complex type evaluation (currently only for extraction of check boxes) + if (o instanceof CTFldChar) { + CTFldChar ctfldChar = ((CTFldChar) o); + if (ctfldChar.getFldCharType() == STFldCharType.BEGIN) { + if (ctfldChar.getFfData() != null) { + for (CTFFCheckBox checkBox : ctfldChar.getFfData().getCheckBoxList()) { + if (checkBox.getDefault().getVal() == STOnOff.X_1) { + text.append("|X|"); + } else { + text.append("|_|"); + } + } + } + } + } + if (o instanceof CTPTab) { text.append("\t"); } @@ -1030,23 +1077,33 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun { } if ("w:cr".equals(tagName) || "cr".equals(tagName)) { text.append("\n"); - } - } - if (o instanceof CTFtnEdnRef) { - CTFtnEdnRef ftn = (CTFtnEdnRef)o; - String footnoteRef = ftn.getDomNode().getLocalName().equals("footnoteReference") ? - "[footnoteRef:" + ftn.getId().intValue() + "]" : "[endnoteRef:" + ftn.getId().intValue() + "]"; - text.append(footnoteRef); - } - } - - c.dispose(); - - // Any picture text? - if(pictureText != null && pictureText.length() > 0) { - text.append("\n").append(pictureText); - } - - return text.toString(); - } -} + } + } + if (o instanceof CTFtnEdnRef) { + CTFtnEdnRef ftn = (CTFtnEdnRef) o; + String footnoteRef = ftn.getDomNode().getLocalName().equals("footnoteReference") ? + "[footnoteRef:" + ftn.getId().intValue() + "]" : "[endnoteRef:" + ftn.getId().intValue() + "]"; + text.append(footnoteRef); + } + } + + c.dispose(); + + // Any picture text? + if (pictureText != null && pictureText.length() > 0) { + text.append("\n").append(pictureText); + } + + return text.toString(); + } + + /** + * @see [MS-OI29500] Run Fonts + */ + public static enum FontCharRange { + ascii /* char 0-127 */, + cs /* complex symbol */, + eastAsia /* east asia */, + hAnsi /* high ansi */ + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDT.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDT.java index 4a51725b1..fd8389ef5 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDT.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDT.java @@ -17,31 +17,30 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtRun; - -/** - * Experimental class to offer rudimentary read-only processing of - * of StructuredDocumentTags/ContentControl - * - * WARNING - APIs expected to change rapidly - * - */ -public class XWPFSDT extends AbstractXWPFSDT - implements IBodyElement, IRunBody, ISDTContents, IRunElement { - private final ISDTContent content; - - public XWPFSDT(CTSdtRun sdtRun, IBody part){ - super(sdtRun.getSdtPr(), part); - this.content = new XWPFSDTContent(sdtRun.getSdtContent(), part, this); - } - - public XWPFSDT(CTSdtBlock block, IBody part){ - super(block.getSdtPr(), part); - this.content = new XWPFSDTContent( block.getSdtContent(), part, this); - } - - public ISDTContent getContent(){ - return content; - } - -} +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtRun; + +/** + * Experimental class to offer rudimentary read-only processing of + * of StructuredDocumentTags/ContentControl + *

    + * WARNING - APIs expected to change rapidly + */ +public class XWPFSDT extends AbstractXWPFSDT + implements IBodyElement, IRunBody, ISDTContents, IRunElement { + private final ISDTContent content; + + public XWPFSDT(CTSdtRun sdtRun, IBody part) { + super(sdtRun.getSdtPr(), part); + this.content = new XWPFSDTContent(sdtRun.getSdtContent(), part, this); + } + + public XWPFSDT(CTSdtBlock block, IBody part) { + super(block.getSdtPr(), part); + this.content = new XWPFSDTContent(block.getSdtContent(), part, this); + } + + public ISDTContent getContent() { + return content; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java index 21cca3e7b..fb40955ef 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java @@ -16,29 +16,28 @@ ==================================================================== */ package org.apache.poi.xwpf.usermodel; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtCell; - -/** - * Experimental class to offer rudimentary read-only processing of - * of StructuredDocumentTags/ContentControl that can appear - * in a table row as if a table cell. - *

    - * These can contain one or more cells or other SDTs within them. - * - * WARNING - APIs expected to change rapidly - * - */ -public class XWPFSDTCell extends AbstractXWPFSDT implements ICell { - private final XWPFSDTContentCell cellContent; - - public XWPFSDTCell(CTSdtCell sdtCell, XWPFTableRow xwpfTableRow, IBody part){ - super(sdtCell.getSdtPr(), part); - cellContent = new XWPFSDTContentCell(sdtCell.getSdtContent(), xwpfTableRow, part); - } - - @Override - public ISDTContent getContent(){ - return cellContent; - } - -} +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtCell; + +/** + * Experimental class to offer rudimentary read-only processing of + * of StructuredDocumentTags/ContentControl that can appear + * in a table row as if a table cell. + *

    + * These can contain one or more cells or other SDTs within them. + *

    + * WARNING - APIs expected to change rapidly + */ +public class XWPFSDTCell extends AbstractXWPFSDT implements ICell { + private final XWPFSDTContentCell cellContent; + + public XWPFSDTCell(CTSdtCell sdtCell, XWPFTableRow xwpfTableRow, IBody part) { + super(sdtCell.getSdtPr(), part); + cellContent = new XWPFSDTContentCell(sdtCell.getSdtContent(), xwpfTableRow, part); + } + + @Override + public ISDTContent getContent() { + return cellContent; + } + +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java index 42c56b377..6942aa749 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContent.java @@ -16,93 +16,91 @@ ==================================================================== */ package org.apache.poi.xwpf.usermodel; -import java.util.ArrayList; -import java.util.List; - - -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; - -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentBlock; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentRun; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; - -/** - * Experimental class to offer rudimentary read-only processing of - * of the contentblock of an SDT/ContentControl. - * - * - * - * WARNING - APIs expected to change rapidly - * - */ -public class XWPFSDTContent implements ISDTContent { - +import java.util.ArrayList; +import java.util.List; + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentBlock; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentRun; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; + +/** + * Experimental class to offer rudimentary read-only processing of + * of the contentblock of an SDT/ContentControl. + *

    + *

    + *

    + * WARNING - APIs expected to change rapidly + */ +public class XWPFSDTContent implements ISDTContent { + // private final IBody part; // private final XWPFDocument document; private List paragraphs = new ArrayList(); private List tables = new ArrayList(); private List runs = new ArrayList(); - private List contentControls = new ArrayList(); - private List bodyElements = new ArrayList(); - - public XWPFSDTContent(CTSdtContentRun sdtRun, IBody part, IRunBody parent){ - for (CTR ctr : sdtRun.getRArray()){ - XWPFRun run = new XWPFRun(ctr, parent); - runs.add(run); - bodyElements.add(run); - } - } - public XWPFSDTContent(CTSdtContentBlock block, IBody part, IRunBody parent){ - XmlCursor cursor = block.newCursor(); - cursor.selectPath("./*"); - while (cursor.toNextSelection()) { + private List contentControls = new ArrayList(); + private List bodyElements = new ArrayList(); + + public XWPFSDTContent(CTSdtContentRun sdtRun, IBody part, IRunBody parent) { + for (CTR ctr : sdtRun.getRArray()) { + XWPFRun run = new XWPFRun(ctr, parent); + runs.add(run); + bodyElements.add(run); + } + } + + public XWPFSDTContent(CTSdtContentBlock block, IBody part, IRunBody parent) { + XmlCursor cursor = block.newCursor(); + cursor.selectPath("./*"); + while (cursor.toNextSelection()) { XmlObject o = cursor.getObject(); if (o instanceof CTP) { XWPFParagraph p = new XWPFParagraph((CTP) o, part); bodyElements.add(p); paragraphs.add(p); } else if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl) o, part); - bodyElements.add(t); - tables.add(t); - } else if (o instanceof CTSdtBlock){ - XWPFSDT c = new XWPFSDT(((CTSdtBlock)o), part); - bodyElements.add(c); - contentControls.add(c); - } else if (o instanceof CTR) { + XWPFTable t = new XWPFTable((CTTbl) o, part); + bodyElements.add(t); + tables.add(t); + } else if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT(((CTSdtBlock) o), part); + bodyElements.add(c); + contentControls.add(c); + } else if (o instanceof CTR) { XWPFRun run = new XWPFRun((CTR) o, parent); runs.add(run); bodyElements.add(run); } - } - } - - public String getText(){ - StringBuilder text = new StringBuilder(); - boolean addNewLine = false; - for (int i = 0; i < bodyElements.size(); i++){ - Object o = bodyElements.get(i); - if (o instanceof XWPFParagraph){ - appendParagraph((XWPFParagraph)o, text); - addNewLine = true; - } else if (o instanceof XWPFTable){ - appendTable((XWPFTable)o, text); - addNewLine = true; - } else if (o instanceof XWPFSDT){ - text.append(((XWPFSDT)o).getContent().getText()); - addNewLine = true; - } else if (o instanceof XWPFRun){ - text.append(((XWPFRun)o).toString()); - addNewLine = false; - } - if (addNewLine == true && i < bodyElements.size()-1){ - text.append("\n"); - } - } + } + } + + public String getText() { + StringBuilder text = new StringBuilder(); + boolean addNewLine = false; + for (int i = 0; i < bodyElements.size(); i++) { + Object o = bodyElements.get(i); + if (o instanceof XWPFParagraph) { + appendParagraph((XWPFParagraph) o, text); + addNewLine = true; + } else if (o instanceof XWPFTable) { + appendTable((XWPFTable) o, text); + addNewLine = true; + } else if (o instanceof XWPFSDT) { + text.append(((XWPFSDT) o).getContent().getText()); + addNewLine = true; + } else if (o instanceof XWPFRun) { + text.append(((XWPFRun) o).toString()); + addNewLine = false; + } + if (addNewLine == true && i < bodyElements.size() - 1) { + text.append("\n"); + } + } return text.toString(); } @@ -110,28 +108,28 @@ public class XWPFSDTContent implements ISDTContent { //this works recursively to pull embedded tables from within cells for (XWPFTableRow row : table.getRows()) { List cells = row.getTableICells(); - for (int i = 0; i < cells.size(); i++) { - ICell cell = cells.get(i); - if (cell instanceof XWPFTableCell) { - text.append(((XWPFTableCell)cell).getTextRecursively()); - } else if (cell instanceof XWPFSDTCell) { - text.append(((XWPFSDTCell)cell).getContent().getText()); - } - if (i < cells.size()-1) { - text.append("\t"); - } - } - text.append('\n'); - } - } - - private void appendParagraph(XWPFParagraph paragraph, StringBuilder text) { - for(IRunElement run : paragraph.getRuns()) { - text.append(run.toString()); - } - } - - public String toString(){ - return getText(); - } + for (int i = 0; i < cells.size(); i++) { + ICell cell = cells.get(i); + if (cell instanceof XWPFTableCell) { + text.append(((XWPFTableCell) cell).getTextRecursively()); + } else if (cell instanceof XWPFSDTCell) { + text.append(((XWPFSDTCell) cell).getContent().getText()); + } + if (i < cells.size() - 1) { + text.append("\t"); + } + } + text.append('\n'); + } + } + + private void appendParagraph(XWPFParagraph paragraph, StringBuilder text) { + for (IRunElement run : paragraph.getRuns()) { + text.append(run.toString()); + } + } + + public String toString() { + return getText(); + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java index 25e258a5c..17f388b59 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java @@ -18,54 +18,52 @@ package org.apache.poi.xwpf.usermodel; import javax.xml.namespace.QName; - -import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlCursor.TokenType; - -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentCell; - - - -/** - * Experimental class to offer rudimentary read-only processing of - * of the XWPFSDTCellContent. - - * WARNING - APIs expected to change rapidly - * - */ -public class XWPFSDTContentCell implements ISDTContent { - + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlCursor.TokenType; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentCell; + + +/** + * Experimental class to offer rudimentary read-only processing of + * of the XWPFSDTCellContent. + *

    + * WARNING - APIs expected to change rapidly + */ +public class XWPFSDTContentCell implements ISDTContent { + //A full implementation would grab the icells //that a content cell can contain. This would require //significant changes, including changing the notion that the //parent of a cell can be not just a row, but an sdt. //For now we are just grabbing the text out of the text tokentypes. - //private List cells = new ArrayList(). + //private List cells = new ArrayList(). + + private String text = ""; + + public XWPFSDTContentCell(CTSdtContentCell sdtContentCell, + XWPFTableRow xwpfTableRow, IBody part) { + super(); + StringBuilder sb = new StringBuilder(); + XmlCursor cursor = sdtContentCell.newCursor(); - private String text = ""; - public XWPFSDTContentCell(CTSdtContentCell sdtContentCell, - XWPFTableRow xwpfTableRow, IBody part){ - super(); - StringBuilder sb = new StringBuilder(); - XmlCursor cursor = sdtContentCell.newCursor(); - - //keep track of the following, - //and add "\n" only before the start of a body - //element if it is not the first body element. - - //index of cell in row - int tcCnt = 0; - //count of body objects + //keep track of the following, + //and add "\n" only before the start of a body + //element if it is not the first body element. + + //index of cell in row + int tcCnt = 0; + //count of body objects int iBodyCnt = 0; int depth = 1; - - while (cursor.hasNextToken() && depth > 0) { - TokenType t = cursor.toNextToken(); - if (t.isText()){ - sb.append(cursor.getTextValue()); - } else if (isStartToken(cursor, "tr")) { - tcCnt = 0; + + while (cursor.hasNextToken() && depth > 0) { + TokenType t = cursor.toNextToken(); + if (t.isText()) { + sb.append(cursor.getTextValue()); + } else if (isStartToken(cursor, "tr")) { + tcCnt = 0; iBodyCnt = 0; } else if (isStartToken(cursor, "tc")) { if (tcCnt++ > 0) { @@ -77,38 +75,37 @@ public class XWPFSDTContentCell implements ISDTContent { isStartToken(cursor, "sdt")) { if (iBodyCnt > 0) { sb.append("\n"); - } - iBodyCnt++; - } - if (cursor.isStart()){ - depth++; - } else if (cursor.isEnd()){ - depth--; - } - } - text = sb.toString(); - } - - - - private boolean isStartToken(XmlCursor cursor, String string) { - if (! cursor.isStart()) { - return false; - } - QName qName = cursor.getName(); + } + iBodyCnt++; + } + if (cursor.isStart()) { + depth++; + } else if (cursor.isEnd()) { + depth--; + } + } + text = sb.toString(); + } + + + private boolean isStartToken(XmlCursor cursor, String string) { + if (!cursor.isStart()) { + return false; + } + QName qName = cursor.getName(); if (qName != null && qName.getLocalPart() != null && qName.getLocalPart().equals(string)) { return true; } return false; - } - - - public String getText(){ - return text; - } - - public String toString(){ - return getText(); - } + } + + + public String getText() { + return text; + } + + public String toString() { + return getText(); + } } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSettings.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSettings.java index 3dcc41aaa..6ce7e2ac3 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSettings.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFSettings.java @@ -59,8 +59,7 @@ public class XWPFSettings extends POIXMLDocumentPart { } @Override - protected void onDocumentRead() throws IOException - { + protected void onDocumentRead() throws IOException { super.onDocumentRead(); readFrom(getPackagePart().getInputStream()); } @@ -74,17 +73,18 @@ public class XWPFSettings extends POIXMLDocumentPart { *

          *    <w:zoom w:percent="50" />
          * 
    +     *
          * @return percentage as an integer of zoom level
          */
         public long getZoomPercent() {
    -       CTZoom zoom;
    -       if (!ctSettings.isSetZoom()) {
    -          zoom = ctSettings.addNewZoom();
    -       } else {
    -          zoom = ctSettings.getZoom();
    -       }
    +        CTZoom zoom;
    +        if (!ctSettings.isSetZoom()) {
    +            zoom = ctSettings.addNewZoom();
    +        } else {
    +            zoom = ctSettings.getZoom();
    +        }
     
    -       return zoom.getPercent().longValue();
    +        return zoom.getPercent().longValue();
         }
     
         /**
    @@ -92,31 +92,31 @@ public class XWPFSettings extends POIXMLDocumentPart {
          * In the zoom tag inside settings.xml file 
    * it sets the value of zoom *
    - * sample snippet from settings.xml + * sample snippet from settings.xml *
    -     *    <w:zoom w:percent="50" /> 
    +     *    <w:zoom w:percent="50" />
          * 
          */
         public void setZoomPercent(long zoomPercent) {
    -       if (! ctSettings.isSetZoom()) {
    -          ctSettings.addNewZoom();
    -       }
    -       CTZoom zoom = ctSettings.getZoom();
    -       zoom.setPercent(BigInteger.valueOf(zoomPercent));
    +        if (!ctSettings.isSetZoom()) {
    +            ctSettings.addNewZoom();
    +        }
    +        CTZoom zoom = ctSettings.getZoom();
    +        zoom.setPercent(BigInteger.valueOf(zoomPercent));
         }
     
         /**
          * Verifies the documentProtection tag inside settings.xml file 
    * if the protection is enforced (w:enforcement="1")
    * and if the kind of protection equals to passed (STDocProtect.Enum editValue)
    - * + *

    *
    * sample snippet from settings.xml *

          *     <w:settings  ... >
          *         <w:documentProtection w:edit="readOnly" w:enforcement="1"/>
          * 
    - * + * * @return true if documentProtection is enforced with option readOnly */ public boolean isEnforcedWith(STDocProtect.Enum editValue) { @@ -152,23 +152,23 @@ public class XWPFSettings extends POIXMLDocumentPart { *
    * sample snippet from settings.xml *
    -     *   <w:documentProtection w:edit="[passed editValue]" w:enforcement="1" 
    +     *   <w:documentProtection w:edit="[passed editValue]" w:enforcement="1"
          *       w:cryptProviderType="rsaAES" w:cryptAlgorithmClass="hash"
          *       w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="14"
          *       w:cryptSpinCount="100000" w:hash="..." w:salt="...."
          *   />
          * 
    - * + * * @param editValue the protection type - * @param password the plaintext password, if null no password will be applied - * @param hashAlgo the hash algorithm - only md2, m5, sha1, sha256, sha384 and sha512 are supported. - * if null, it will default default to sha1 + * @param password the plaintext password, if null no password will be applied + * @param hashAlgo the hash algorithm - only md2, m5, sha1, sha256, sha384 and sha512 are supported. + * if null, it will default default to sha1 */ public void setEnforcementEditValue(org.openxmlformats.schemas.wordprocessingml.x2006.main.STDocProtect.Enum editValue, - String password, HashAlgorithm hashAlgo) { + String password, HashAlgorithm hashAlgo) { safeGetDocumentProtection().setEnforcement(STOnOff.X_1); safeGetDocumentProtection().setEdit(editValue); - + if (password == null) { if (safeGetDocumentProtection().isSetCryptProviderType()) { safeGetDocumentProtection().unsetCryptProviderType(); @@ -177,23 +177,23 @@ public class XWPFSettings extends POIXMLDocumentPart { if (safeGetDocumentProtection().isSetCryptAlgorithmClass()) { safeGetDocumentProtection().unsetCryptAlgorithmClass(); } - + if (safeGetDocumentProtection().isSetCryptAlgorithmType()) { safeGetDocumentProtection().unsetCryptAlgorithmType(); } - + if (safeGetDocumentProtection().isSetCryptAlgorithmSid()) { safeGetDocumentProtection().unsetCryptAlgorithmSid(); } - + if (safeGetDocumentProtection().isSetSalt()) { safeGetDocumentProtection().unsetSalt(); } - + if (safeGetDocumentProtection().isSetCryptSpinCount()) { safeGetDocumentProtection().unsetCryptSpinCount(); } - + if (safeGetDocumentProtection().isSetHash()) { safeGetDocumentProtection().unsetHash(); } @@ -201,47 +201,47 @@ public class XWPFSettings extends POIXMLDocumentPart { final STCryptProv.Enum providerType; final int sid; switch (hashAlgo) { - case md2: - providerType = STCryptProv.RSA_FULL; - sid = 1; - break; - case md4: - providerType = STCryptProv.RSA_FULL; - sid = 2; - break; - case md5: - providerType = STCryptProv.RSA_FULL; - sid = 3; - break; - case sha1: - providerType = STCryptProv.RSA_FULL; - sid = 4; - break; - case sha256: - providerType = STCryptProv.RSA_AES; - sid = 12; - break; - case sha384: - providerType = STCryptProv.RSA_AES; - sid = 13; - break; - case sha512: - providerType = STCryptProv.RSA_AES; - sid = 14; - break; - default: - throw new EncryptedDocumentException - ("Hash algorithm '"+hashAlgo+"' is not supported for document write protection."); + case md2: + providerType = STCryptProv.RSA_FULL; + sid = 1; + break; + case md4: + providerType = STCryptProv.RSA_FULL; + sid = 2; + break; + case md5: + providerType = STCryptProv.RSA_FULL; + sid = 3; + break; + case sha1: + providerType = STCryptProv.RSA_FULL; + sid = 4; + break; + case sha256: + providerType = STCryptProv.RSA_AES; + sid = 12; + break; + case sha384: + providerType = STCryptProv.RSA_AES; + sid = 13; + break; + case sha512: + providerType = STCryptProv.RSA_AES; + sid = 14; + break; + default: + throw new EncryptedDocumentException + ("Hash algorithm '" + hashAlgo + "' is not supported for document write protection."); } - - SecureRandom random = new SecureRandom(); + + SecureRandom random = new SecureRandom(); byte salt[] = random.generateSeed(16); - + // Iterations specifies the number of times the hashing function shall be iteratively run (using each // iteration's result as the input for the next iteration). int spinCount = 100000; - + if (hashAlgo == null) hashAlgo = HashAlgorithm.sha1; String legacyHash = CryptoFunctions.xorHashPasswordReversed(password); @@ -257,7 +257,7 @@ public class XWPFSettings extends POIXMLDocumentPart { safeGetDocumentProtection().setCryptAlgorithmClass(STAlgClass.HASH); safeGetDocumentProtection().setCryptProviderType(providerType); safeGetDocumentProtection().setCryptAlgorithmSid(BigInteger.valueOf(sid)); - } + } } /** @@ -271,30 +271,45 @@ public class XWPFSettings extends POIXMLDocumentPart { byte hash[] = safeGetDocumentProtection().getHash(); byte salt[] = safeGetDocumentProtection().getSalt(); BigInteger spinCount = safeGetDocumentProtection().getCryptSpinCount(); - + if (sid == null || hash == null || salt == null || spinCount == null) return false; - + HashAlgorithm hashAlgo; switch (sid.intValue()) { - case 1: hashAlgo = HashAlgorithm.md2; break; - case 2: hashAlgo = HashAlgorithm.md4; break; - case 3: hashAlgo = HashAlgorithm.md5; break; - case 4: hashAlgo = HashAlgorithm.sha1; break; - case 12: hashAlgo = HashAlgorithm.sha256; break; - case 13: hashAlgo = HashAlgorithm.sha384; break; - case 14: hashAlgo = HashAlgorithm.sha512; break; - default: return false; + case 1: + hashAlgo = HashAlgorithm.md2; + break; + case 2: + hashAlgo = HashAlgorithm.md4; + break; + case 3: + hashAlgo = HashAlgorithm.md5; + break; + case 4: + hashAlgo = HashAlgorithm.sha1; + break; + case 12: + hashAlgo = HashAlgorithm.sha256; + break; + case 13: + hashAlgo = HashAlgorithm.sha384; + break; + case 14: + hashAlgo = HashAlgorithm.sha512; + break; + default: + return false; } - + String legacyHash = CryptoFunctions.xorHashPasswordReversed(password); // Implementation Notes List: // --> In this third stage, the reversed byte order legacy hash from the second stage shall // be converted to Unicode hex string representation byte hash2[] = CryptoFunctions.hashPassword(legacyHash, hashAlgo, salt, spinCount.intValue(), false); - + return Arrays.equals(hash, hash2); } - + /** * Removes protection enforcement.
    * In the documentProtection tag inside settings.xml file
    @@ -308,18 +323,18 @@ public class XWPFSettings extends POIXMLDocumentPart { * Enforces fields update on document open (in Word). * In the settings.xml file
    * sets the updateSettings value to true (w:updateSettings w:val="true") - * - * NOTICES: - *
      - *
    • Causing Word to ask on open: "This document contains fields that may refer to other files. Do you want to update the fields in this document?" - * (if "Update automatic links at open" is enabled)
    • - *
    • Flag is removed after saving with changes in Word
    • - *
    + *

    + * NOTICES: + *

      + *
    • Causing Word to ask on open: "This document contains fields that may refer to other files. Do you want to update the fields in this document?" + * (if "Update automatic links at open" is enabled)
    • + *
    • Flag is removed after saving with changes in Word
    • + *
    */ public void setUpdateFields() { - CTOnOff onOff = CTOnOff.Factory.newInstance(); - onOff.setVal(STOnOff.TRUE); - ctSettings.setUpdateFields(onOff); + CTOnOff onOff = CTOnOff.Factory.newInstance(); + onOff.setVal(STOnOff.TRUE); + ctSettings.setUpdateFields(onOff); } boolean isUpdateFields() { @@ -328,7 +343,7 @@ public class XWPFSettings extends POIXMLDocumentPart { /** * Check if revision tracking is turned on. - * + * * @return true if revision tracking is turned on */ public boolean isTrackRevisions() { @@ -337,16 +352,16 @@ public class XWPFSettings extends POIXMLDocumentPart { /** * Enable or disable revision tracking. - * + * * @param enable true to turn on revision tracking, false to turn off revision tracking */ public void setTrackRevisions(boolean enable) { - if(enable) { - if(!ctSettings.isSetTrackRevisions()) { + if (enable) { + if (!ctSettings.isSetTrackRevisions()) { ctSettings.addNewTrackRevisions(); } } else { - if(ctSettings.isSetTrackRevisions()) { + if (ctSettings.isSetTrackRevisions()) { ctSettings.unsetTrackRevisions(); } } @@ -355,7 +370,7 @@ public class XWPFSettings extends POIXMLDocumentPart { @Override protected void commit() throws IOException { if (ctSettings == null) { - throw new IllegalStateException("Unable to write out settings that were never read in!"); + throw new IllegalStateException("Unable to write out settings that were never read in!"); } XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyle.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyle.java index 2ceff9719..a6ebdcc71 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyle.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyle.java @@ -19,128 +19,141 @@ package org.apache.poi.xwpf.usermodel; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType; - -/** - * @author Philipp Epp - * - */ -public class XWPFStyle { - - private CTStyle ctStyle; - protected XWPFStyles styles; - - /** - * constructor - * @param style - */ - public XWPFStyle(CTStyle style){ - this(style,null); - } - /** - * constructor - * @param style - * @param styles - */ - public XWPFStyle(CTStyle style, XWPFStyles styles){ - this.ctStyle = style; - this.styles = styles; - } - - /** - * get StyleID of the style - * @return styleID StyleID of the style - */ - public String getStyleId(){ - return ctStyle.getStyleId(); - } - - /** - * get Type of the Style - * @return ctType - */ - public STStyleType.Enum getType(){ - return ctStyle.getType(); - } - - /** - * set style - * @param style - */ - public void setStyle(CTStyle style){ - this.ctStyle = style; - } - /** - * get ctStyle - * @return ctStyle - */ - public CTStyle getCTStyle(){ - return this.ctStyle; - } - /** - * set styleID - * @param styleId - */ - public void setStyleId(String styleId){ - ctStyle.setStyleId(styleId); - } - - /** - * set styleType - * @param type - */ - public void setType(STStyleType.Enum type){ - ctStyle.setType(type); - } - /** - * get styles - * @return styles the styles to which this style belongs - */ - public XWPFStyles getStyles(){ - return styles; - } - - public String getBasisStyleID(){ - if(ctStyle.getBasedOn()!=null) - return ctStyle.getBasedOn().getVal(); - else - return null; - } - - - /** - * get StyleID of the linked Style - */ - public String getLinkStyleID(){ - if (ctStyle.getLink()!=null) - return ctStyle.getLink().getVal(); - else - return null; - } - - /** - * get StyleID of the next style - */ - public String getNextStyleID(){ - if(ctStyle.getNext()!=null) - return ctStyle.getNext().getVal(); - else - return null; - } - - public String getName() { - if(ctStyle.isSetName()) - return ctStyle.getName().getVal(); - return null; - } - - /** - * compares the names of the Styles - * @param compStyle - */ - public boolean hasSameName(XWPFStyle compStyle){ - CTStyle ctCompStyle = compStyle.getCTStyle(); - String name = ctCompStyle.getName().getVal(); - return name.equals(ctStyle.getName().getVal()); - } - -}//end class + +/** + * @author Philipp Epp + */ +public class XWPFStyle { + + protected XWPFStyles styles; + private CTStyle ctStyle; + + /** + * constructor + * + * @param style + */ + public XWPFStyle(CTStyle style) { + this(style, null); + } + + /** + * constructor + * + * @param style + * @param styles + */ + public XWPFStyle(CTStyle style, XWPFStyles styles) { + this.ctStyle = style; + this.styles = styles; + } + + /** + * get StyleID of the style + * + * @return styleID StyleID of the style + */ + public String getStyleId() { + return ctStyle.getStyleId(); + } + + /** + * set styleID + * + * @param styleId + */ + public void setStyleId(String styleId) { + ctStyle.setStyleId(styleId); + } + + /** + * get Type of the Style + * + * @return ctType + */ + public STStyleType.Enum getType() { + return ctStyle.getType(); + } + + /** + * set styleType + * + * @param type + */ + public void setType(STStyleType.Enum type) { + ctStyle.setType(type); + } + + /** + * set style + * + * @param style + */ + public void setStyle(CTStyle style) { + this.ctStyle = style; + } + + /** + * get ctStyle + * + * @return ctStyle + */ + public CTStyle getCTStyle() { + return this.ctStyle; + } + + /** + * get styles + * + * @return styles the styles to which this style belongs + */ + public XWPFStyles getStyles() { + return styles; + } + + public String getBasisStyleID() { + if (ctStyle.getBasedOn() != null) + return ctStyle.getBasedOn().getVal(); + else + return null; + } + + + /** + * get StyleID of the linked Style + */ + public String getLinkStyleID() { + if (ctStyle.getLink() != null) + return ctStyle.getLink().getVal(); + else + return null; + } + + /** + * get StyleID of the next style + */ + public String getNextStyleID() { + if (ctStyle.getNext() != null) + return ctStyle.getNext().getVal(); + else + return null; + } + + public String getName() { + if (ctStyle.isSetName()) + return ctStyle.getName().getVal(); + return null; + } + + /** + * compares the names of the Styles + * + * @param compStyle + */ + public boolean hasSameName(XWPFStyle compStyle) { + CTStyle ctCompStyle = compStyle.getCTStyle(); + String name = ctCompStyle.getName().getVal(); + return name.equals(ctStyle.getName().getVal()); + } + +}//end class diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java index 824d39d71..ed3960179 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFStyles.java @@ -31,281 +31,295 @@ import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.xmlbeans.XmlException; -import org.apache.xmlbeans.XmlOptions; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.StylesDocument; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPrDefault; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLanguage; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocDefaults; -/** - * @author Philipp Epp - * - */ -public class XWPFStyles extends POIXMLDocumentPart{ - - private List listStyle = new ArrayList(); - private CTStyles ctStyles; - XWPFLatentStyles latentStyles; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlOptions; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocDefaults; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLanguage; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPrDefault; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPrDefault; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.StylesDocument; + +/** + * Holds details of built-in, default and user styles, which + * apply to tables / paragraphs / lists etc. + * Text within one of those with custom stylings has the style + * information stored in the {@link XWPFRun} + */ +public class XWPFStyles extends POIXMLDocumentPart { + private CTStyles ctStyles; + private List listStyle = new ArrayList(); + + private XWPFLatentStyles latentStyles; + private XWPFDefaultRunStyle defaultRunStyle; + private XWPFDefaultParagraphStyle defaultParaStyle; /** * Construct XWPFStyles from a package part * - * @param part the package part holding the data of the styles, - * @param rel the package relationship of type "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" - */ - - public XWPFStyles(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException{ - super(part, rel); - } - - /** - * Construct XWPFStyles from scratch for a new document. - */ - public XWPFStyles() { - } - - /** - * Read document - */ - @Override - protected void onDocumentRead() throws IOException{ - StylesDocument stylesDoc; - try { - InputStream is = getPackagePart().getInputStream(); - stylesDoc = StylesDocument.Factory.parse(is); - setStyles(stylesDoc.getStyles()); - latentStyles = new XWPFLatentStyles(ctStyles.getLatentStyles(), this); - } catch (XmlException e) { - throw new POIXMLException("Unable to read styles", e); - } - - - } - - @Override - protected void commit() throws IOException { - if (ctStyles == null) { - throw new IllegalStateException("Unable to write out styles that were never read in!"); - } - - XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); - xmlOptions.setSaveSyntheticDocumentElement(new QName(CTStyles.type.getName().getNamespaceURI(), "styles")); - Map map = new HashMap(); - map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); - map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w"); - xmlOptions.setSaveSuggestedPrefixes(map); - PackagePart part = getPackagePart(); - OutputStream out = part.getOutputStream(); - ctStyles.save(out, xmlOptions); - out.close(); - } - + * @param part the package part holding the data of the styles, + * @param rel the package relationship of type "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" + */ + public XWPFStyles(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException { + super(part, rel); + } + /** - * Sets the ctStyles - * @param styles + * Construct XWPFStyles from scratch for a new document. */ - @SuppressWarnings("deprecation") - public void setStyles(CTStyles styles) { - ctStyles = styles; - - // Build up all the style objects - for(CTStyle style : ctStyles.getStyleArray()) { - listStyle.add(new XWPFStyle(style, this)); - } + public XWPFStyles() { } - - /** - * checks whether style with styleID exist - * @param styleID styleID of the Style in the style-Document - * @return true if style exist, false if style not exist - */ - public boolean styleExist(String styleID){ - for (XWPFStyle style : listStyle) { - if (style.getStyleId().equals(styleID)) - return true; - } - return false; - } - /** - * add a style to the document - * @param style - * @throws IOException - */ - public void addStyle(XWPFStyle style){ - listStyle.add(style); - ctStyles.addNewStyle(); - int pos = ctStyles.sizeOfStyleArray() - 1; - ctStyles.setStyleArray(pos, style.getCTStyle()); - } - /** - *get style by a styleID - * @param styleID styleID of the searched style - * @return style - */ - public XWPFStyle getStyle(String styleID){ - for (XWPFStyle style : listStyle) { - if(style.getStyleId().equals(styleID)) - return style; - } - return null; - } - /** - * get the styles which are related to the parameter style and their relatives - * this method can be used to copy all styles from one document to another document - * @param style - * @return a list of all styles which were used by this method - */ - public List getUsedStyleList(XWPFStyle style){ - List usedStyleList = new ArrayList(); - usedStyleList.add(style); - return getUsedStyleList(style, usedStyleList); - } - - /** - * get the styles which are related to parameter style - * @param style - * @return all Styles of the parameterList - */ - private List getUsedStyleList(XWPFStyle style, List usedStyleList){ - String basisStyleID = style.getBasisStyleID(); - XWPFStyle basisStyle = getStyle(basisStyleID); - if((basisStyle!=null)&&(!usedStyleList.contains(basisStyle))){ - usedStyleList.add(basisStyle); - getUsedStyleList(basisStyle, usedStyleList); - } - String linkStyleID = style.getLinkStyleID(); - XWPFStyle linkStyle = getStyle(linkStyleID); - if((linkStyle!=null)&&(!usedStyleList.contains(linkStyle))){ - usedStyleList.add(linkStyle); - getUsedStyleList(linkStyle, usedStyleList); - } - - String nextStyleID = style.getNextStyleID(); - XWPFStyle nextStyle = getStyle(nextStyleID); - if((nextStyle!=null)&&(!usedStyleList.contains(nextStyle))){ - usedStyleList.add(linkStyle); - getUsedStyleList(linkStyle, usedStyleList); - } - return usedStyleList; - } - - /** - * Sets the default spelling language on ctStyles DocDefaults parameter - * @param strSpellingLanguage - */ - public void setSpellingLanguage(String strSpellingLanguage) { - CTDocDefaults docDefaults = null; - CTRPr runProps = null; - CTLanguage lang = null; + /** + * Read document + */ + @Override + protected void onDocumentRead() throws IOException { + StylesDocument stylesDoc; + try { + InputStream is = getPackagePart().getInputStream(); + stylesDoc = StylesDocument.Factory.parse(is); + setStyles(stylesDoc.getStyles()); + latentStyles = new XWPFLatentStyles(ctStyles.getLatentStyles(), this); + } catch (XmlException e) { + throw new POIXMLException("Unable to read styles", e); + } + } - // Just making sure we use the members that have already been defined - if(ctStyles.isSetDocDefaults()) { - docDefaults = ctStyles.getDocDefaults(); - if(docDefaults.isSetRPrDefault()) { - CTRPrDefault RPrDefault = docDefaults.getRPrDefault(); - if(RPrDefault.isSetRPr()) { - runProps = RPrDefault.getRPr(); - if(runProps.isSetLang()) - lang = runProps.getLang(); - } - } - } + @Override + protected void commit() throws IOException { + if (ctStyles == null) { + throw new IllegalStateException("Unable to write out styles that were never read in!"); + } + + XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); + xmlOptions.setSaveSyntheticDocumentElement(new QName(CTStyles.type.getName().getNamespaceURI(), "styles")); + Map map = new HashMap(); + map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r"); + map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w"); + xmlOptions.setSaveSuggestedPrefixes(map); + PackagePart part = getPackagePart(); + OutputStream out = part.getOutputStream(); + ctStyles.save(out, xmlOptions); + out.close(); + } + + protected void ensureDocDefaults() { + if (!ctStyles.isSetDocDefaults()) { + ctStyles.addNewDocDefaults(); + } + + CTDocDefaults docDefaults = ctStyles.getDocDefaults(); + if (!docDefaults.isSetPPrDefault()) + docDefaults.addNewPPrDefault(); + if (!docDefaults.isSetRPrDefault()) + docDefaults.addNewRPrDefault(); + + CTPPrDefault pprd = docDefaults.getPPrDefault(); + CTRPrDefault rprd = docDefaults.getRPrDefault(); + if (!pprd.isSetPPr()) pprd.addNewPPr(); + if (!rprd.isSetRPr()) rprd.addNewRPr(); + + defaultRunStyle = new XWPFDefaultRunStyle(rprd.getRPr()); + defaultParaStyle = new XWPFDefaultParagraphStyle(pprd.getPPr()); + } + + /** + * Sets the ctStyles + * + * @param styles + */ + @SuppressWarnings("deprecation") + public void setStyles(CTStyles styles) { + ctStyles = styles; + + // Build up all the style objects + for (CTStyle style : ctStyles.getStyleArray()) { + listStyle.add(new XWPFStyle(style, this)); + } + if (ctStyles.isSetDocDefaults()) { + CTDocDefaults docDefaults = ctStyles.getDocDefaults(); + if (docDefaults.isSetRPrDefault() && docDefaults.getRPrDefault().isSetRPr()) { + defaultRunStyle = new XWPFDefaultRunStyle( + docDefaults.getRPrDefault().getRPr()); + } + if (docDefaults.isSetPPrDefault() && docDefaults.getPPrDefault().isSetPPr()) { + defaultParaStyle = new XWPFDefaultParagraphStyle( + docDefaults.getPPrDefault().getPPr()); + } + } + } + + /** + * checks whether style with styleID exist + * + * @param styleID styleID of the Style in the style-Document + * @return true if style exist, false if style not exist + */ + public boolean styleExist(String styleID) { + for (XWPFStyle style : listStyle) { + if (style.getStyleId().equals(styleID)) + return true; + } + return false; + } + + /** + * add a style to the document + * + * @param style + * @throws IOException + */ + public void addStyle(XWPFStyle style) { + listStyle.add(style); + ctStyles.addNewStyle(); + int pos = ctStyles.sizeOfStyleArray() - 1; + ctStyles.setStyleArray(pos, style.getCTStyle()); + } + + /** + * Get style by a styleID + * + * @param styleID styleID of the searched style + * @return style + */ + public XWPFStyle getStyle(String styleID) { + for (XWPFStyle style : listStyle) { + if (style.getStyleId().equals(styleID)) + return style; + } + return null; + } + + public int getNumberOfStyles() { + return listStyle.size(); + } + + /** + * get the styles which are related to the parameter style and their relatives + * this method can be used to copy all styles from one document to another document + * + * @param style + * @return a list of all styles which were used by this method + */ + public List getUsedStyleList(XWPFStyle style) { + List usedStyleList = new ArrayList(); + usedStyleList.add(style); + return getUsedStyleList(style, usedStyleList); + } + + /** + * get the styles which are related to parameter style + * + * @param style + * @return all Styles of the parameterList + */ + private List getUsedStyleList(XWPFStyle style, List usedStyleList) { + String basisStyleID = style.getBasisStyleID(); + XWPFStyle basisStyle = getStyle(basisStyleID); + if ((basisStyle != null) && (!usedStyleList.contains(basisStyle))) { + usedStyleList.add(basisStyle); + getUsedStyleList(basisStyle, usedStyleList); + } + String linkStyleID = style.getLinkStyleID(); + XWPFStyle linkStyle = getStyle(linkStyleID); + if ((linkStyle != null) && (!usedStyleList.contains(linkStyle))) { + usedStyleList.add(linkStyle); + getUsedStyleList(linkStyle, usedStyleList); + } + + String nextStyleID = style.getNextStyleID(); + XWPFStyle nextStyle = getStyle(nextStyleID); + if ((nextStyle != null) && (!usedStyleList.contains(nextStyle))) { + usedStyleList.add(linkStyle); + getUsedStyleList(linkStyle, usedStyleList); + } + return usedStyleList; + } + + protected CTLanguage getCTLanguage() { + ensureDocDefaults(); + + CTLanguage lang = null; + if (defaultRunStyle.getRPr().isSetLang()) { + lang = defaultRunStyle.getRPr().getLang(); + } else { + lang = defaultRunStyle.getRPr().addNewLang(); + } + + return lang; + } + + /** + * Sets the default spelling language on ctStyles DocDefaults parameter + * + * @param strSpellingLanguage + */ + public void setSpellingLanguage(String strSpellingLanguage) { + CTLanguage lang = getCTLanguage(); + lang.setVal(strSpellingLanguage); + lang.setBidi(strSpellingLanguage); + } + + /** + * Sets the default East Asia spelling language on ctStyles DocDefaults parameter + * + * @param strEastAsia + */ + public void setEastAsia(String strEastAsia) { + CTLanguage lang = getCTLanguage(); + lang.setEastAsia(strEastAsia); + } - if(docDefaults == null) - docDefaults = ctStyles.addNewDocDefaults(); - if(runProps == null) - runProps = docDefaults.addNewRPrDefault().addNewRPr(); - if(lang == null) - lang = runProps.addNewLang(); + /** + * Sets the default font on ctStyles DocDefaults parameter + * TODO Replace this with specific setters for each type, possibly + * on XWPFDefaultRunStyle + */ + public void setDefaultFonts(CTFonts fonts) { + ensureDocDefaults(); + + CTRPr runProps = defaultRunStyle.getRPr(); + runProps.setRFonts(fonts); + } - lang.setVal(strSpellingLanguage); - lang.setBidi(strSpellingLanguage); - } + /** + * get the style with the same name + * if this style is not existing, return null + */ + public XWPFStyle getStyleWithSameName(XWPFStyle style) { + for (XWPFStyle ownStyle : listStyle) { + if (ownStyle.hasSameName(style)) { + return ownStyle; + } + } + return null; + } - /** - * Sets the default East Asia spelling language on ctStyles DocDefaults parameter - * @param strEastAsia - */ - public void setEastAsia(String strEastAsia) { - CTDocDefaults docDefaults = null; - CTRPr runProps = null; - CTLanguage lang = null; + /** + * Get the default style which applies text runs in the document + */ + public XWPFDefaultRunStyle getDefaultRunStyle() { + ensureDocDefaults(); + return defaultRunStyle; + } - // Just making sure we use the members that have already been defined - if(ctStyles.isSetDocDefaults()) { - docDefaults = ctStyles.getDocDefaults(); - if(docDefaults.isSetRPrDefault()) { - CTRPrDefault RPrDefault = docDefaults.getRPrDefault(); - if(RPrDefault.isSetRPr()) { - runProps = RPrDefault.getRPr(); - if(runProps.isSetLang()) - lang = runProps.getLang(); - } - } - } + /** + * Get the default paragraph style which applies to the document + */ + public XWPFDefaultParagraphStyle getDefaultParagraphStyle() { + ensureDocDefaults(); + return defaultParaStyle; + } - if(docDefaults == null) - docDefaults = ctStyles.addNewDocDefaults(); - if(runProps == null) - runProps = docDefaults.addNewRPrDefault().addNewRPr(); - if(lang == null) - lang = runProps.addNewLang(); - - lang.setEastAsia(strEastAsia); - } - - /** - * Sets the default font on ctStyles DocDefaults parameter - * @param fonts - */ - public void setDefaultFonts(CTFonts fonts) { - CTDocDefaults docDefaults = null; - CTRPr runProps = null; - - // Just making sure we use the members that have already been defined - if(ctStyles.isSetDocDefaults()) { - docDefaults = ctStyles.getDocDefaults(); - if(docDefaults.isSetRPrDefault()) { - CTRPrDefault RPrDefault = docDefaults.getRPrDefault(); - if(RPrDefault.isSetRPr()) { - runProps = RPrDefault.getRPr(); - } - } - } - - if(docDefaults == null) - docDefaults = ctStyles.addNewDocDefaults(); - if(runProps == null) - runProps = docDefaults.addNewRPrDefault().addNewRPr(); - - runProps.setRFonts(fonts); - } - - - /** - * get latentstyles - */ - public XWPFLatentStyles getLatentStyles() { - return latentStyles; - } - - /** - * get the style with the same name - * if this style is not existing, return null - */ - public XWPFStyle getStyleWithSameName(XWPFStyle style){ - for (XWPFStyle ownStyle : listStyle) { - if(ownStyle.hasSameName(style)){ - return ownStyle; - } - } - return null; - - } -}//end class + /** + * Get the definition of all the Latent Styles + */ + public XWPFLatentStyles getLatentStyles() { + return latentStyles; + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java index 643d28ffa..1f4fd2b38 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTable.java @@ -44,19 +44,10 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth; * of paragraphs (and other block-level content) arranged in rows and columns.

    */ public class XWPFTable implements IBodyElement, ISDTContents { - protected StringBuffer text = new StringBuffer(); - private CTTbl ctTbl; - protected List tableRows; - protected List styleIDs; - - // Create a map from this XWPF-level enum to the STBorder.Enum values - public static enum XWPFBorderType { NIL, NONE, SINGLE, THICK, DOUBLE, DOTTED, DASHED, DOT_DASH }; private static EnumMap xwpfBorderTypeMap; // Create a map from the STBorder.Enum values to the XWPF-level enums private static HashMap stBorderTypeMap; - protected IBody part; - static { // populate enum maps xwpfBorderTypeMap = new EnumMap(XWPFBorderType.class); @@ -77,9 +68,17 @@ public class XWPFTable implements IBodyElement, ISDTContents { stBorderTypeMap.put(STBorder.INT_DOUBLE, XWPFBorderType.DOUBLE); stBorderTypeMap.put(STBorder.INT_DOTTED, XWPFBorderType.DOTTED); stBorderTypeMap.put(STBorder.INT_DASHED, XWPFBorderType.DASHED); - stBorderTypeMap.put(STBorder.INT_DOT_DASH, XWPFBorderType.DOT_DASH); + stBorderTypeMap.put(STBorder.INT_DOT_DASH, XWPFBorderType.DOT_DASH); } - + + protected StringBuffer text = new StringBuffer(); + protected List tableRows; + + ; + protected List styleIDs; + protected IBody part; + private CTTbl ctTbl; + public XWPFTable(CTTbl table, IBody part, int row, int col) { this(table, part); @@ -94,7 +93,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { } @SuppressWarnings("deprecation") - public XWPFTable(CTTbl table, IBody part){ + public XWPFTable(CTTbl table, IBody part) { this.part = part; this.ctTbl = table; @@ -163,9 +162,9 @@ public class XWPFTable implements IBodyElement, ISDTContents { * Convenience method to extract text in cells. This * does not extract text recursively in cells, and it does not * currently include text in SDT (form) components. - *

    + *

    * To get all text within a table, see XWPFWordExtractor's appendTableText - * as an example. + * as an example. * * @return text */ @@ -216,6 +215,13 @@ public class XWPFTable implements IBodyElement, ISDTContents { return null; } + /** + * @return width value + */ + public int getWidth() { + CTTblPr tblPr = getTrPr(); + return tblPr.isSetTblW() ? tblPr.getTblW().getW().intValue() : -1; + } /** * @param width @@ -226,14 +232,6 @@ public class XWPFTable implements IBodyElement, ISDTContents { tblWidth.setW(new BigInteger("" + width)); } - /** - * @return width value - */ - public int getWidth() { - CTTblPr tblPr = getTrPr(); - return tblPr.isSetTblW() ? tblPr.getTblW().getW().intValue() : -1; - } - /** * @return number of rows in table */ @@ -253,12 +251,13 @@ public class XWPFTable implements IBodyElement, ISDTContents { } } } - + /** * get the StyleID of the table - * @return style-ID of the table + * + * @return style-ID of the table */ - public String getStyleID(){ + public String getStyleID() { String styleId = null; CTTblPr tblPr = ctTbl.getTblPr(); if (tblPr != null) { @@ -273,6 +272,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * Set the table style. If the style is not defined in the document, MS Word * will set the table style to "Normal". + * * @param styleName - the style name to apply to this table */ public void setStyleID(String styleName) { @@ -523,24 +523,25 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * add a new Row to the table - * - * @param row the row which should be added + * + * @param row the row which should be added */ - public void addRow(XWPFTableRow row){ + public void addRow(XWPFTableRow row) { ctTbl.addNewTr(); - ctTbl.setTrArray(getNumberOfRows()-1, row.getCtRow()); + ctTbl.setTrArray(getNumberOfRows() - 1, row.getCtRow()); tableRows.add(row); } /** * add a new Row to the table * at position pos - * @param row the row which should be added + * + * @param row the row which should be added */ - public boolean addRow(XWPFTableRow row, int pos){ - if(pos >= 0 && pos <= tableRows.size()){ + public boolean addRow(XWPFTableRow row, int pos) { + if (pos >= 0 && pos <= tableRows.size()) { ctTbl.insertNewTr(pos); - ctTbl.setTrArray(pos,row.getCtRow()); + ctTbl.setTrArray(pos, row.getCtRow()); tableRows.add(pos, row); return true; } @@ -548,12 +549,13 @@ public class XWPFTable implements IBodyElement, ISDTContents { } /** - * inserts a new tablerow + * inserts a new tablerow + * * @param pos - * @return the inserted row + * @return the inserted row */ - public XWPFTableRow insertNewTableRow(int pos){ - if(pos >= 0 && pos <= tableRows.size()){ + public XWPFTableRow insertNewTableRow(int pos) { + if (pos >= 0 && pos <= tableRows.size()) { CTRow row = ctTbl.insertNewTr(pos); XWPFTableRow tableRow = new XWPFTableRow(row, this); tableRows.add(pos, tableRow); @@ -562,10 +564,10 @@ public class XWPFTable implements IBodyElement, ISDTContents { return null; } - /** * Remove a row at position pos from the table - * @param pos position the Row in the Table + * + * @param pos position the Row in the Table */ public boolean removeRow(int pos) throws IndexOutOfBoundsException { if (pos >= 0 && pos < tableRows.size()) { @@ -582,9 +584,9 @@ public class XWPFTable implements IBodyElement, ISDTContents { return tableRows; } - /** * returns the type of the BodyElement Table + * * @see org.apache.poi.xwpf.usermodel.IBodyElement#getElementType() */ public BodyElementType getElementType() { @@ -597,10 +599,11 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * returns the part of the bodyElement + * * @see org.apache.poi.xwpf.usermodel.IBody#getPart() */ public POIXMLDocumentPart getPart() { - if(part != null){ + if (part != null) { return part.getPart(); } return null; @@ -608,6 +611,7 @@ public class XWPFTable implements IBodyElement, ISDTContents { /** * returns the partType of the bodyPart which owns the bodyElement + * * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() */ public BodyType getPartType() { @@ -619,9 +623,14 @@ public class XWPFTable implements IBodyElement, ISDTContents { * if this row is not existing in the table null will be returned */ public XWPFTableRow getRow(CTRow row) { - for(int i=0; i paragraphs = null; - protected List tables = null; - protected List bodyElements = null; - protected IBody part; - private XWPFTableRow tableRow = null; - // Create a map from this XWPF-level enum to the STVerticalJc.Enum values - public static enum XWPFVertAlign { TOP, CENTER, BOTH, BOTTOM }; - private static EnumMap alignMap; - // Create a map from the STVerticalJc.Enum values to the XWPF-level enums - private static HashMap stVertAlignTypeMap; + +/** + * Represents a Cell within a {@link XWPFTable}. The + * Cell is the thing that holds the actual content (paragraphs etc) + */ +public class XWPFTableCell implements IBody, ICell { + private static EnumMap alignMap; + // Create a map from the STVerticalJc.Enum values to the XWPF-level enums + private static HashMap stVertAlignTypeMap; static { // populate enum maps @@ -68,337 +60,343 @@ public class XWPFTableCell implements IBody, ICell { stVertAlignTypeMap.put(STVerticalJc.INT_CENTER, XWPFVertAlign.CENTER); stVertAlignTypeMap.put(STVerticalJc.INT_BOTH, XWPFVertAlign.BOTH); stVertAlignTypeMap.put(STVerticalJc.INT_BOTTOM, XWPFVertAlign.BOTTOM); - - } - - /** - * If a table cell does not include at least one block-level element, then this document shall be considered corrupt - */ + + } + + private final CTTc ctTc; + protected List paragraphs = null; + protected List tables = null; + protected List bodyElements = null; + + ; + protected IBody part; + private XWPFTableRow tableRow = null; + + /** + * If a table cell does not include at least one block-level element, then this document shall be considered corrupt + */ public XWPFTableCell(CTTc cell, XWPFTableRow tableRow, IBody part) { this.ctTc = cell; - this.part = part; - this.tableRow = tableRow; - // NB: If a table cell does not include at least one block-level element, then this document shall be considered corrupt. - if(cell.sizeOfPArray()<1) - cell.addNewP(); - bodyElements = new ArrayList(); - paragraphs = new ArrayList(); + this.part = part; + this.tableRow = tableRow; + // NB: If a table cell does not include at least one block-level element, then this document shall be considered corrupt. + if (cell.sizeOfPArray() < 1) + cell.addNewP(); + bodyElements = new ArrayList(); + paragraphs = new ArrayList(); tables = new ArrayList(); XmlCursor cursor = ctTc.newCursor(); cursor.selectPath("./*"); - while (cursor.toNextSelection()) { - XmlObject o = cursor.getObject(); - if (o instanceof CTP) { - XWPFParagraph p = new XWPFParagraph((CTP)o, this); - paragraphs.add(p); - bodyElements.add(p); - } - if (o instanceof CTTbl) { - XWPFTable t = new XWPFTable((CTTbl)o, this); - tables.add(t); - bodyElements.add(t); - } - if (o instanceof CTSdtBlock){ - XWPFSDT c = new XWPFSDT((CTSdtBlock)o, this); - bodyElements.add(c); - } - if (o instanceof CTSdtRun){ - XWPFSDT c = new XWPFSDT((CTSdtRun)o, this); - System.out.println(c.getContent().getText()); - bodyElements.add(c); - } - } - cursor.dispose(); + while (cursor.toNextSelection()) { + XmlObject o = cursor.getObject(); + if (o instanceof CTP) { + XWPFParagraph p = new XWPFParagraph((CTP) o, this); + paragraphs.add(p); + bodyElements.add(p); + } + if (o instanceof CTTbl) { + XWPFTable t = new XWPFTable((CTTbl) o, this); + tables.add(t); + bodyElements.add(t); + } + if (o instanceof CTSdtBlock) { + XWPFSDT c = new XWPFSDT((CTSdtBlock) o, this); + bodyElements.add(c); + } + if (o instanceof CTSdtRun) { + XWPFSDT c = new XWPFSDT((CTSdtRun) o, this); + System.out.println(c.getContent().getText()); + bodyElements.add(c); + } + } + cursor.dispose(); + } + + @Internal + public CTTc getCTTc() { + return ctTc; } - - - @Internal - public CTTc getCTTc() { - return ctTc; - } - - /** - * returns an Iterator with paragraphs and tables - * @see org.apache.poi.xwpf.usermodel.IBody#getBodyElements() - */ - public List getBodyElements(){ - return Collections.unmodifiableList(bodyElements); - } - - public void setParagraph(XWPFParagraph p) { - if (ctTc.sizeOfPArray() == 0) { - ctTc.addNewP(); + + /** + * returns an Iterator with paragraphs and tables + * + * @see org.apache.poi.xwpf.usermodel.IBody#getBodyElements() + */ + public List getBodyElements() { + return Collections.unmodifiableList(bodyElements); + } + + public void setParagraph(XWPFParagraph p) { + if (ctTc.sizeOfPArray() == 0) { + ctTc.addNewP(); } ctTc.setPArray(0, p.getCTP()); } - /** - * returns a list of paragraphs - */ - public List getParagraphs(){ - return paragraphs; - } - - /** - * Add a Paragraph to this Table Cell - * @return The paragraph which was added - */ - public XWPFParagraph addParagraph() { - XWPFParagraph p = new XWPFParagraph(ctTc.addNewP(), this); - addParagraph(p); - return p; - } - - /** - * add a Paragraph to this TableCell - * @param p the paragaph which has to be added - */ - public void addParagraph(XWPFParagraph p){ - paragraphs.add(p); - } - - /** - * removes a paragraph of this tablecell - * @param pos - */ - public void removeParagraph(int pos){ - paragraphs.remove(pos); - ctTc.removeP(pos); - } - - /** - * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this table - * the method will return this paragraph - * if there is no corresponding {@link XWPFParagraph} the method will return null - * @param p is instance of CTP and is searching for an XWPFParagraph - * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this table - * XWPFParagraph with the correspondig CTP p - */ - public XWPFParagraph getParagraph(CTP p){ - for (XWPFParagraph paragraph : paragraphs) { - if(p.equals(paragraph.getCTP())){ - return paragraph; - } - } - return null; - } - - public void setText(String text) { - CTP ctP = (ctTc.sizeOfPArray() == 0) ? ctTc.addNewP() : ctTc.getPArray(0); - XWPFParagraph par = new XWPFParagraph(ctP, this); - par.createRun().setText(text); - } - - public XWPFTableRow getTableRow(){ - return tableRow; - } - - /** - * Set cell color. This sets some associated values; for finer control - * you may want to access these elements individually. - * @param rgbStr - the desired cell color, in the hex form "RRGGBB". - */ - public void setColor(String rgbStr) { - CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr(); - CTShd ctshd = tcpr.isSetShd() ? tcpr.getShd() : tcpr.addNewShd(); - ctshd.setColor("auto"); - ctshd.setVal(STShd.CLEAR); - ctshd.setFill(rgbStr); - } - - /** - * Get cell color. Note that this method only returns the "fill" value. - * @return RGB string of cell color - */ - public String getColor() { - String color = null; - CTTcPr tcpr = ctTc.getTcPr(); - if (tcpr != null) { - CTShd ctshd = tcpr.getShd(); - if (ctshd != null) { - color = ctshd.xgetFill().getStringValue(); - } - } - return color; - } - - /** - * Set the vertical alignment of the cell. - * @param vAlign - the desired alignment enum value - */ - public void setVerticalAlignment(XWPFVertAlign vAlign) { - CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr(); - CTVerticalJc va = tcpr.addNewVAlign(); - va.setVal(alignMap.get(vAlign)); - } - - /** - * Get the vertical alignment of the cell. - * @return the cell alignment enum value - */ - public XWPFVertAlign getVerticalAlignment() { - XWPFVertAlign vAlign = null; - CTTcPr tcpr = ctTc.getTcPr(); - if (ctTc != null) { - CTVerticalJc va = tcpr.getVAlign(); - vAlign = stVertAlignTypeMap.get(va.getVal().intValue()); - } - return vAlign; - } - - /** - * add a new paragraph at position of the cursor - * @param cursor - * @return the inserted paragraph - */ - public XWPFParagraph insertNewParagraph(XmlCursor cursor){ - if(!isCursorInTableCell(cursor)) { - return null; - } - - String uri = CTP.type.getName().getNamespaceURI(); - String localPart = "p"; - cursor.beginElement(localPart,uri); - cursor.toParent(); - CTP p = (CTP)cursor.getObject(); - XWPFParagraph newP = new XWPFParagraph(p, this); - XmlObject o = null; - while(!(o instanceof CTP)&&(cursor.toPrevSibling())){ - o = cursor.getObject(); - } - if((!(o instanceof CTP)) || (CTP)o == p){ - paragraphs.add(0, newP); - } - else{ - int pos = paragraphs.indexOf(getParagraph((CTP)o))+1; - paragraphs.add(pos,newP); - } - int i=0; - cursor.toCursor(p.newCursor()); - while(cursor.toPrevSibling()){ - o =cursor.getObject(); - if(o instanceof CTP || o instanceof CTTbl) - i++; - } - bodyElements.add(i, newP); - cursor.toCursor(p.newCursor()); - cursor.toEndToken(); - return newP; - } - - public XWPFTable insertNewTbl(XmlCursor cursor) { - if(isCursorInTableCell(cursor)){ - String uri = CTTbl.type.getName().getNamespaceURI(); - String localPart = "tbl"; - cursor.beginElement(localPart,uri); - cursor.toParent(); - CTTbl t = (CTTbl)cursor.getObject(); - XWPFTable newT = new XWPFTable(t, this); - cursor.removeXmlContents(); - XmlObject o = null; - while(!(o instanceof CTTbl)&&(cursor.toPrevSibling())){ - o = cursor.getObject(); - } - if(!(o instanceof CTTbl)){ - tables.add(0, newT); - } - else{ - int pos = tables.indexOf(getTable((CTTbl)o))+1; - tables.add(pos,newT); - } - int i=0; - cursor = t.newCursor(); - while(cursor.toPrevSibling()){ - o =cursor.getObject(); - if(o instanceof CTP || o instanceof CTTbl) - i++; - } - bodyElements.add(i, newT); - cursor = t.newCursor(); - cursor.toEndToken(); - return newT; - } - return null; - } - - /** - * verifies that cursor is on the right position - */ - private boolean isCursorInTableCell(XmlCursor cursor) { - XmlCursor verify = cursor.newCursor(); - verify.toParent(); - if(verify.getObject() == this.ctTc){ - return true; - } - return false; - } - - - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int) - */ - public XWPFParagraph getParagraphArray(int pos) { - if(pos > 0 && pos < paragraphs.size()){ - return paragraphs.get(pos); - } - return null; - } - - /** - * get the to which the TableCell belongs - * - * @see org.apache.poi.xwpf.usermodel.IBody#getPart() - */ - public POIXMLDocumentPart getPart() { - return tableRow.getTable().getPart(); - } - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() - */ - public BodyType getPartType() { - return BodyType.TABLECELL; - } - - - /** - * get a table by its CTTbl-Object - * @see org.apache.poi.xwpf.usermodel.IBody#getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) - */ - public XWPFTable getTable(CTTbl ctTable) { - for(int i=0; i 0 && pos < tables.size()){ - return tables.get(pos); - } - return null; - } - - - /** - * @see org.apache.poi.xwpf.usermodel.IBody#getTables() - */ - public List getTables() { - return Collections.unmodifiableList(tables); - } - - - /** - * inserts an existing XWPFTable to the arrays bodyElements and tables - * @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int, org.apache.poi.xwpf.usermodel.XWPFTable) - */ - @SuppressWarnings("deprecation") + /** + * returns a list of paragraphs + */ + public List getParagraphs() { + return paragraphs; + } + + /** + * Add a Paragraph to this Table Cell + * + * @return The paragraph which was added + */ + public XWPFParagraph addParagraph() { + XWPFParagraph p = new XWPFParagraph(ctTc.addNewP(), this); + addParagraph(p); + return p; + } + + /** + * add a Paragraph to this TableCell + * + * @param p the paragaph which has to be added + */ + public void addParagraph(XWPFParagraph p) { + paragraphs.add(p); + } + + /** + * removes a paragraph of this tablecell + * + * @param pos + */ + public void removeParagraph(int pos) { + paragraphs.remove(pos); + ctTc.removeP(pos); + } + + /** + * if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this table + * the method will return this paragraph + * if there is no corresponding {@link XWPFParagraph} the method will return null + * + * @param p is instance of CTP and is searching for an XWPFParagraph + * @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this table + * XWPFParagraph with the correspondig CTP p + */ + public XWPFParagraph getParagraph(CTP p) { + for (XWPFParagraph paragraph : paragraphs) { + if (p.equals(paragraph.getCTP())) { + return paragraph; + } + } + return null; + } + + public XWPFTableRow getTableRow() { + return tableRow; + } + + /** + * Get cell color. Note that this method only returns the "fill" value. + * + * @return RGB string of cell color + */ + public String getColor() { + String color = null; + CTTcPr tcpr = ctTc.getTcPr(); + if (tcpr != null) { + CTShd ctshd = tcpr.getShd(); + if (ctshd != null) { + color = ctshd.xgetFill().getStringValue(); + } + } + return color; + } + + /** + * Set cell color. This sets some associated values; for finer control + * you may want to access these elements individually. + * + * @param rgbStr - the desired cell color, in the hex form "RRGGBB". + */ + public void setColor(String rgbStr) { + CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr(); + CTShd ctshd = tcpr.isSetShd() ? tcpr.getShd() : tcpr.addNewShd(); + ctshd.setColor("auto"); + ctshd.setVal(STShd.CLEAR); + ctshd.setFill(rgbStr); + } + + /** + * Get the vertical alignment of the cell. + * + * @return the cell alignment enum value + */ + public XWPFVertAlign getVerticalAlignment() { + XWPFVertAlign vAlign = null; + CTTcPr tcpr = ctTc.getTcPr(); + if (ctTc != null) { + CTVerticalJc va = tcpr.getVAlign(); + vAlign = stVertAlignTypeMap.get(va.getVal().intValue()); + } + return vAlign; + } + + /** + * Set the vertical alignment of the cell. + * + * @param vAlign - the desired alignment enum value + */ + public void setVerticalAlignment(XWPFVertAlign vAlign) { + CTTcPr tcpr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr(); + CTVerticalJc va = tcpr.addNewVAlign(); + va.setVal(alignMap.get(vAlign)); + } + + /** + * add a new paragraph at position of the cursor + * + * @param cursor + * @return the inserted paragraph + */ + public XWPFParagraph insertNewParagraph(XmlCursor cursor) { + if (!isCursorInTableCell(cursor)) { + return null; + } + + String uri = CTP.type.getName().getNamespaceURI(); + String localPart = "p"; + cursor.beginElement(localPart, uri); + cursor.toParent(); + CTP p = (CTP) cursor.getObject(); + XWPFParagraph newP = new XWPFParagraph(p, this); + XmlObject o = null; + while (!(o instanceof CTP) && (cursor.toPrevSibling())) { + o = cursor.getObject(); + } + if ((!(o instanceof CTP)) || (CTP) o == p) { + paragraphs.add(0, newP); + } else { + int pos = paragraphs.indexOf(getParagraph((CTP) o)) + 1; + paragraphs.add(pos, newP); + } + int i = 0; + cursor.toCursor(p.newCursor()); + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) + i++; + } + bodyElements.add(i, newP); + cursor.toCursor(p.newCursor()); + cursor.toEndToken(); + return newP; + } + + public XWPFTable insertNewTbl(XmlCursor cursor) { + if (isCursorInTableCell(cursor)) { + String uri = CTTbl.type.getName().getNamespaceURI(); + String localPart = "tbl"; + cursor.beginElement(localPart, uri); + cursor.toParent(); + CTTbl t = (CTTbl) cursor.getObject(); + XWPFTable newT = new XWPFTable(t, this); + cursor.removeXmlContents(); + XmlObject o = null; + while (!(o instanceof CTTbl) && (cursor.toPrevSibling())) { + o = cursor.getObject(); + } + if (!(o instanceof CTTbl)) { + tables.add(0, newT); + } else { + int pos = tables.indexOf(getTable((CTTbl) o)) + 1; + tables.add(pos, newT); + } + int i = 0; + cursor = t.newCursor(); + while (cursor.toPrevSibling()) { + o = cursor.getObject(); + if (o instanceof CTP || o instanceof CTTbl) + i++; + } + bodyElements.add(i, newT); + cursor = t.newCursor(); + cursor.toEndToken(); + return newT; + } + return null; + } + + /** + * verifies that cursor is on the right position + */ + private boolean isCursorInTableCell(XmlCursor cursor) { + XmlCursor verify = cursor.newCursor(); + verify.toParent(); + if (verify.getObject() == this.ctTc) { + return true; + } + return false; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int) + */ + public XWPFParagraph getParagraphArray(int pos) { + if (pos > 0 && pos < paragraphs.size()) { + return paragraphs.get(pos); + } + return null; + } + + /** + * get the to which the TableCell belongs + * + * @see org.apache.poi.xwpf.usermodel.IBody#getPart() + */ + public POIXMLDocumentPart getPart() { + return tableRow.getTable().getPart(); + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getPartType() + */ + public BodyType getPartType() { + return BodyType.TABLECELL; + } + + /** + * get a table by its CTTbl-Object + * + * @see org.apache.poi.xwpf.usermodel.IBody#getTable(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) + */ + public XWPFTable getTable(CTTbl ctTable) { + for (int i = 0; i < tables.size(); i++) { + if (getTables().get(i).getCTTbl() == ctTable) return getTables().get(i); + } + return null; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int) + */ + public XWPFTable getTableArray(int pos) { + if (pos > 0 && pos < tables.size()) { + return tables.get(pos); + } + return null; + } + + /** + * @see org.apache.poi.xwpf.usermodel.IBody#getTables() + */ + public List getTables() { + return Collections.unmodifiableList(tables); + } + + /** + * inserts an existing XWPFTable to the arrays bodyElements and tables + * + * @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int, org.apache.poi.xwpf.usermodel.XWPFTable) + */ + @SuppressWarnings("deprecation") public void insertTable(int pos, XWPFTable table) { bodyElements.add(pos, table); int i = 0; @@ -408,90 +406,101 @@ public class XWPFTableCell implements IBody, ICell { } i++; } - tables.add(i, table); - } - - public String getText(){ - StringBuffer text = new StringBuffer(); - for (XWPFParagraph p : paragraphs) { - text.append(p.getText()); - } - return text.toString(); + tables.add(i, table); + } + + public String getText() { + StringBuffer text = new StringBuffer(); + for (XWPFParagraph p : paragraphs) { + text.append(p.getText()); + } + return text.toString(); + } + + public void setText(String text) { + CTP ctP = (ctTc.sizeOfPArray() == 0) ? ctTc.addNewP() : ctTc.getPArray(0); + XWPFParagraph par = new XWPFParagraph(ctP, this); + par.createRun().setText(text); + } + + /** + * extracts all text recursively through embedded tables and embedded SDTs + */ + public String getTextRecursively() { + + StringBuffer text = new StringBuffer(); + for (int i = 0; i < bodyElements.size(); i++) { + boolean isLast = (i == bodyElements.size() - 1) ? true : false; + appendBodyElementText(text, bodyElements.get(i), isLast); + } + + return text.toString(); + } + + private void appendBodyElementText(StringBuffer text, IBodyElement e, boolean isLast) { + if (e instanceof XWPFParagraph) { + text.append(((XWPFParagraph) e).getText()); + if (isLast == false) { + text.append('\t'); + } + } else if (e instanceof XWPFTable) { + XWPFTable eTable = (XWPFTable) e; + for (XWPFTableRow row : eTable.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + List localBodyElements = cell.getBodyElements(); + for (int i = 0; i < localBodyElements.size(); i++) { + boolean localIsLast = (i == localBodyElements.size() - 1) ? true : false; + appendBodyElementText(text, localBodyElements.get(i), localIsLast); + } + } + } + + if (isLast == false) { + text.append('\n'); + } + } else if (e instanceof XWPFSDT) { + text.append(((XWPFSDT) e).getContent().getText()); + if (isLast == false) { + text.append('\t'); + } + } } /** - * extracts all text recursively through embedded tables and embedded SDTs - */ - public String getTextRecursively(){ - - StringBuffer text = new StringBuffer(); - for (int i = 0; i < bodyElements.size(); i++){ - boolean isLast = (i== bodyElements.size()-1)? true : false; - appendBodyElementText(text, bodyElements.get(i), isLast); - } - - return text.toString(); - } - - private void appendBodyElementText(StringBuffer text, IBodyElement e, boolean isLast){ - if (e instanceof XWPFParagraph){ - text.append(((XWPFParagraph)e).getText()); - if (isLast == false){ - text.append('\t'); - } - } else if (e instanceof XWPFTable){ - XWPFTable eTable = (XWPFTable)e; - for (XWPFTableRow row : eTable.getRows()){ - for (XWPFTableCell cell : row.getTableCells()){ - List localBodyElements = cell.getBodyElements(); - for (int i = 0; i < localBodyElements.size(); i++){ - boolean localIsLast = (i== localBodyElements.size()-1)? true : false; - appendBodyElementText(text, localBodyElements.get(i), localIsLast); - } - } - } - - if (isLast == false){ - text.append('\n'); - } - } else if (e instanceof XWPFSDT){ - text.append(((XWPFSDT)e).getContent().getText()); - if (isLast == false){ - text.append('\t'); - } - } - } - - /** - * get the TableCell which belongs to the TableCell - */ - public XWPFTableCell getTableCell(CTTc cell) { - XmlCursor cursor = cell.newCursor(); - cursor.toParent(); - XmlObject o = cursor.getObject(); - if(!(o instanceof CTRow)){ - return null; - } - CTRow row = (CTRow)o; - cursor.toParent(); - o = cursor.getObject(); - cursor.dispose(); - if(! (o instanceof CTTbl)){ - return null; - } - CTTbl tbl = (CTTbl) o; - XWPFTable table = getTable(tbl); - if(table == null){ - return null; - } - XWPFTableRow tableRow = table.getRow(row); - if (tableRow == null) { - return null; - } - return tableRow.getTableCell(cell); - } - - public XWPFDocument getXWPFDocument() { - return part.getXWPFDocument(); - } -} + * get the TableCell which belongs to the TableCell + */ + public XWPFTableCell getTableCell(CTTc cell) { + XmlCursor cursor = cell.newCursor(); + cursor.toParent(); + XmlObject o = cursor.getObject(); + if (!(o instanceof CTRow)) { + return null; + } + CTRow row = (CTRow) o; + cursor.toParent(); + o = cursor.getObject(); + cursor.dispose(); + if (!(o instanceof CTTbl)) { + return null; + } + CTTbl tbl = (CTTbl) o; + XWPFTable table = getTable(tbl); + if (table == null) { + return null; + } + XWPFTableRow tableRow = table.getRow(row); + if (tableRow == null) { + return null; + } + return tableRow.getTableCell(cell); + } + + public XWPFDocument getXWPFDocument() { + return part.getXWPFDocument(); + } + + // Create a map from this XWPF-level enum to the STVerticalJc.Enum values + public static enum XWPFVertAlign { + TOP, CENTER, BOTH, BOTTOM + } +} diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java index 627ee3c8d..5a947efc7 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java @@ -31,14 +31,14 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff; - -/** - * A row within an {@link XWPFTable}. Rows mostly just have - * sizings and stylings, the interesting content lives inside - * the child {@link XWPFTableCell}s - */ -public class XWPFTableRow { - private CTRow ctRow; + +/** + * A row within an {@link XWPFTable}. Rows mostly just have + * sizings and stylings, the interesting content lives inside + * the child {@link XWPFTableCell}s + */ +public class XWPFTableRow { + private CTRow ctRow; private XWPFTable table; private List tableCells; @@ -52,187 +52,195 @@ public class XWPFTableRow { public CTRow getCtRow() { return ctRow; } - - /** - * create a new XWPFTableCell and add it to the tableCell-list of this tableRow - * @return the newly created XWPFTableCell - */ - public XWPFTableCell createCell() { - XWPFTableCell tableCell = new XWPFTableCell(ctRow.addNewTc(), this, table.getBody()); - tableCells.add(tableCell); - return tableCell; - } - - public XWPFTableCell getCell(int pos) { - if (pos >= 0 && pos < ctRow.sizeOfTcArray()) { - return getTableCells().get(pos); - } - return null; - } - - public void removeCell(int pos) { - if (pos >= 0 && pos < ctRow.sizeOfTcArray()) { - tableCells.remove(pos); - } - } - /** - * adds a new TableCell at the end of this tableRow - */ - public XWPFTableCell addNewTableCell(){ - CTTc cell = ctRow.addNewTc(); - XWPFTableCell tableCell = new XWPFTableCell(cell, this, table.getBody()); - tableCells.add(tableCell); - return tableCell; - } - - /** + + /** + * create a new XWPFTableCell and add it to the tableCell-list of this tableRow + * + * @return the newly created XWPFTableCell + */ + public XWPFTableCell createCell() { + XWPFTableCell tableCell = new XWPFTableCell(ctRow.addNewTc(), this, table.getBody()); + tableCells.add(tableCell); + return tableCell; + } + + public XWPFTableCell getCell(int pos) { + if (pos >= 0 && pos < ctRow.sizeOfTcArray()) { + return getTableCells().get(pos); + } + return null; + } + + public void removeCell(int pos) { + if (pos >= 0 && pos < ctRow.sizeOfTcArray()) { + tableCells.remove(pos); + } + } + + /** + * adds a new TableCell at the end of this tableRow + */ + public XWPFTableCell addNewTableCell() { + CTTc cell = ctRow.addNewTc(); + XWPFTableCell tableCell = new XWPFTableCell(cell, this, table.getBody()); + tableCells.add(tableCell); + return tableCell; + } + + /** * This element specifies the height of the current table row within the * current table. This height shall be used to determine the resulting * height of the table row, which may be absolute or relative (depending on * its attribute values). If omitted, then the table row shall automatically - * resize its height to the height required by its contents (the equivalent - * of an hRule value of auto). - * - * @param height - */ - public void setHeight(int height) { - CTTrPr properties = getTrPr(); - CTHeight h = properties.sizeOfTrHeightArray() == 0 ? properties.addNewTrHeight() : properties.getTrHeightArray(0); - h.setVal(new BigInteger("" + height)); - } - - /** + * resize its height to the height required by its contents (the equivalent + * of an hRule value of auto). + * + * @return height + */ + public int getHeight() { + CTTrPr properties = getTrPr(); + return properties.sizeOfTrHeightArray() == 0 ? 0 : properties.getTrHeightArray(0).getVal().intValue(); + } + + /** * This element specifies the height of the current table row within the * current table. This height shall be used to determine the resulting * height of the table row, which may be absolute or relative (depending on * its attribute values). If omitted, then the table row shall automatically - * resize its height to the height required by its contents (the equivalent - * of an hRule value of auto). - * - * @return height - */ - public int getHeight() { - CTTrPr properties = getTrPr(); - return properties.sizeOfTrHeightArray() == 0 ? 0 : properties.getTrHeightArray(0).getVal().intValue(); - } - - private CTTrPr getTrPr() { - return (ctRow.isSetTrPr()) ? ctRow.getTrPr() : ctRow.addNewTrPr(); - } - - public XWPFTable getTable(){ - return table; - } - - /** - * create and return a list of all XWPFTableCell - * who belongs to this row - * @return a list of {@link XWPFTableCell} - */ - public List getTableICells(){ - - List cells = new ArrayList(); - //Can't use ctRow.getTcList because that only gets table cells - //Can't use ctRow.getSdtList because that only gets sdts that are at cell level + * resize its height to the height required by its contents (the equivalent + * of an hRule value of auto). + * + * @param height + */ + public void setHeight(int height) { + CTTrPr properties = getTrPr(); + CTHeight h = properties.sizeOfTrHeightArray() == 0 ? properties.addNewTrHeight() : properties.getTrHeightArray(0); + h.setVal(new BigInteger("" + height)); + } + + private CTTrPr getTrPr() { + return (ctRow.isSetTrPr()) ? ctRow.getTrPr() : ctRow.addNewTrPr(); + } + + public XWPFTable getTable() { + return table; + } + + /** + * create and return a list of all XWPFTableCell + * who belongs to this row + * + * @return a list of {@link XWPFTableCell} + */ + public List getTableICells() { + + List cells = new ArrayList(); + //Can't use ctRow.getTcList because that only gets table cells + //Can't use ctRow.getSdtList because that only gets sdts that are at cell level XmlCursor cursor = ctRow.newCursor(); - cursor.selectPath("./*"); - while (cursor.toNextSelection()) { - XmlObject o = cursor.getObject(); - if (o instanceof CTTc){ - cells.add(new XWPFTableCell((CTTc)o, this, table.getBody())); - } else if (o instanceof CTSdtCell) { - cells.add(new XWPFSDTCell((CTSdtCell)o, this, table.getBody())); - } - } - return cells; + cursor.selectPath("./*"); + while (cursor.toNextSelection()) { + XmlObject o = cursor.getObject(); + if (o instanceof CTTc) { + cells.add(new XWPFTableCell((CTTc) o, this, table.getBody())); + } else if (o instanceof CTSdtCell) { + cells.add(new XWPFSDTCell((CTSdtCell) o, this, table.getBody())); + } + } + return cells; } - /** - * create and return a list of all XWPFTableCell - * who belongs to this row - * @return a list of {@link XWPFTableCell} - */ - @SuppressWarnings("deprecation") - public List getTableCells(){ - if(tableCells == null){ - List cells = new ArrayList(); - for (CTTc tableCell : ctRow.getTcArray()) { - cells.add(new XWPFTableCell(tableCell, this, table.getBody())); - } - //TODO: it is possible to have an SDT that contains a cell in within a row - //need to modify this code so that it pulls out SDT wrappers around cells, too. - - this.tableCells = cells; - } - return tableCells; - } - - /** + /** + * create and return a list of all XWPFTableCell + * who belongs to this row + * + * @return a list of {@link XWPFTableCell} + */ + @SuppressWarnings("deprecation") + public List getTableCells() { + if (tableCells == null) { + List cells = new ArrayList(); + for (CTTc tableCell : ctRow.getTcArray()) { + cells.add(new XWPFTableCell(tableCell, this, table.getBody())); + } + //TODO: it is possible to have an SDT that contains a cell in within a row + //need to modify this code so that it pulls out SDT wrappers around cells, too. + + this.tableCells = cells; + } + return tableCells; + } + + /** * returns the XWPFTableCell which belongs to the CTTC cell - * if there is no XWPFTableCell which belongs to the parameter CTTc cell null will be returned - */ - public XWPFTableCell getTableCell(CTTc cell) { - for(int i=0; i 0) { - CTOnOff onoff = trpr.getCantSplitArray(0); - isCant = onoff.getVal().equals(STOnOff.ON); - } - return isCant; - } - - /** - * This attribute controls whether to repeat a table's header row at the top - * of a table split across pages. - * @param repeat - if TRUE, repeat header row at the top of each page of table; - * if FALSE, don't repeat header row. - */ - public void setRepeatHeader(boolean repeat) { - CTTrPr trpr = getTrPr(); - CTOnOff onoff = trpr.addNewTblHeader(); - onoff.setVal(repeat ? STOnOff.ON : STOnOff.OFF); - } - - /** - * Return true if a table's header row should be repeated at the top of a - * table split across pages. - * @return true if table's header row should be repeated at the top of each - * page of table, false otherwise. - */ - public boolean isRepeatHeader() { - boolean repeat = false; - CTTrPr trpr = getTrPr(); - if (trpr.sizeOfTblHeaderArray() > 0) { - CTOnOff rpt = trpr.getTblHeaderArray(0); - repeat = rpt.getVal().equals(STOnOff.ON); - } - return repeat; - } -} + * if there is no XWPFTableCell which belongs to the parameter CTTc cell null will be returned + */ + public XWPFTableCell getTableCell(CTTc cell) { + for (int i = 0; i < tableCells.size(); i++) { + if (tableCells.get(i).getCTTc() == cell) + return tableCells.get(i); + } + return null; + } + + /** + * Return true if the "can't split row" value is true. The logic for this + * attribute is a little unusual: a TRUE value means DON'T allow rows to + * split, FALSE means allow rows to split. + * + * @return true if rows can't be split, false otherwise. + */ + public boolean isCantSplitRow() { + boolean isCant = false; + CTTrPr trpr = getTrPr(); + if (trpr.sizeOfCantSplitArray() > 0) { + CTOnOff onoff = trpr.getCantSplitArray(0); + isCant = onoff.getVal().equals(STOnOff.ON); + } + return isCant; + } + + /** + * This attribute controls whether to allow table rows to split across pages. + * The logic for this attribute is a little unusual: a true value means + * DON'T allow rows to split, false means allow rows to split. + * + * @param split - if true, don't allow rows to be split. If false, allow + * rows to be split. + */ + public void setCantSplitRow(boolean split) { + CTTrPr trpr = getTrPr(); + CTOnOff onoff = trpr.addNewCantSplit(); + onoff.setVal(split ? STOnOff.ON : STOnOff.OFF); + } + + /** + * Return true if a table's header row should be repeated at the top of a + * table split across pages. + * + * @return true if table's header row should be repeated at the top of each + * page of table, false otherwise. + */ + public boolean isRepeatHeader() { + boolean repeat = false; + CTTrPr trpr = getTrPr(); + if (trpr.sizeOfTblHeaderArray() > 0) { + CTOnOff rpt = trpr.getTblHeaderArray(0); + repeat = rpt.getVal().equals(STOnOff.ON); + } + return repeat; + } + + /** + * This attribute controls whether to repeat a table's header row at the top + * of a table split across pages. + * + * @param repeat - if TRUE, repeat header row at the top of each page of table; + * if FALSE, don't repeat header row. + */ + public void setRepeatHeader(boolean repeat) { + CTTrPr trpr = getTrPr(); + CTOnOff onoff = trpr.addNewTblHeader(); + onoff.setVal(repeat ? STOnOff.ON : STOnOff.OFF); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java b/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java index f4e39ab65..55f4093fb 100644 --- a/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java +++ b/src/ooxml/testcases/org/apache/poi/TestPOIXMLDocument.java @@ -155,13 +155,16 @@ public final class TestPOIXMLDocument extends TestCase { public void testRelationOrder() throws Exception { OPCPackage pkg = PackageHelper.open(POIDataSamples.getDocumentInstance().openResourceAsStream("WordWithAttachments.docx")); OPCParser doc = new OPCParser(pkg); - doc.parse(new TestFactory()); - - for(POIXMLDocumentPart rel : doc.getRelations()){ - //TODO finish me - assertNotNull(rel); + try { + doc.parse(new TestFactory()); + + for(POIXMLDocumentPart rel : doc.getRelations()){ + //TODO finish me + assertNotNull(rel); + } + } finally { + doc.close(); } - } public void testCommitNullPart() throws IOException, InvalidFormatException { diff --git a/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java b/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java index 7f79afaad..a8644f420 100644 --- a/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java +++ b/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java @@ -25,6 +25,7 @@ import junit.framework.TestCase; import org.apache.poi.POIDataSamples; import org.apache.poi.POIOLE2TextExtractor; import org.apache.poi.POITextExtractor; +import org.apache.poi.POIXMLException; import org.apache.poi.POIXMLTextExtractor; import org.apache.poi.hdgf.extractor.VisioTextExtractor; import org.apache.poi.hpbf.extractor.PublisherTextExtractor; @@ -47,252 +48,290 @@ import org.apache.poi.xwpf.extractor.XWPFWordExtractor; * Test that the extractor factory plays nicely */ public class TestExtractorFactory extends TestCase { + private File txt; - private File txt; + private File xls; + private File xlsx; + private File xlsxStrict; + private File xltx; + private File xlsEmb; - private File xls; - private File xlsx; - private File xltx; - private File xlsEmb; + private File doc; + private File doc6; + private File doc95; + private File docx; + private File dotx; + private File docEmb; + private File docEmbOOXML; - private File doc; - private File doc6; - private File doc95; - private File docx; - private File dotx; - private File docEmb; - private File docEmbOOXML; + private File ppt; + private File pptx; - private File ppt; - private File pptx; + private File msg; + private File msgEmb; + private File msgEmbMsg; - private File msg; - private File msgEmb; - private File msgEmbMsg; - - private File vsd; - - private File pub; + private File vsd; + private File vsdx; - private File getFileAndCheck(POIDataSamples samples, String name) { - File file = samples.getFile(name); - - assertNotNull("Did not get a file for " + name, file); - assertTrue("Did not get a type file for " + name, file.isFile()); - assertTrue("File did not exist: " + name, file.exists()); - - return file; - } - @Override - protected void setUp() throws Exception { - super.setUp(); + private File pub; - POIDataSamples ssTests = POIDataSamples.getSpreadSheetInstance(); - xls = getFileAndCheck(ssTests, "SampleSS.xls"); - xlsx = getFileAndCheck(ssTests, "SampleSS.xlsx"); - xltx = getFileAndCheck(ssTests, "test.xltx"); - xlsEmb = getFileAndCheck(ssTests, "excel_with_embeded.xls"); + private File getFileAndCheck(POIDataSamples samples, String name) { + File file = samples.getFile(name); - POIDataSamples wpTests = POIDataSamples.getDocumentInstance(); - doc = getFileAndCheck(wpTests, "SampleDoc.doc"); - doc6 = getFileAndCheck(wpTests, "Word6.doc"); - doc95 = getFileAndCheck(wpTests, "Word95.doc"); - docx = getFileAndCheck(wpTests, "SampleDoc.docx"); - dotx = getFileAndCheck(wpTests, "test.dotx"); - docEmb = getFileAndCheck(wpTests, "word_with_embeded.doc"); - docEmbOOXML = getFileAndCheck(wpTests, "word_with_embeded_ooxml.doc"); + assertNotNull("Did not get a file for " + name, file); + assertTrue("Did not get a type file for " + name, file.isFile()); + assertTrue("File did not exist: " + name, file.exists()); - POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - ppt = getFileAndCheck(slTests, "SampleShow.ppt"); - pptx = getFileAndCheck(slTests, "SampleShow.pptx"); - txt = getFileAndCheck(slTests, "SampleShow.txt"); + return file; + } + @Override + protected void setUp() throws Exception { + super.setUp(); - POIDataSamples dgTests = POIDataSamples.getDiagramInstance(); - vsd = getFileAndCheck(dgTests, "Test_Visio-Some_Random_Text.vsd"); - - POIDataSamples pubTests = POIDataSamples.getPublisherInstance(); - pub = getFileAndCheck(pubTests, "Simple.pub"); - - POIDataSamples olTests = POIDataSamples.getHSMFInstance(); - msg = getFileAndCheck(olTests, "quick.msg"); - msgEmb = getFileAndCheck(olTests, "attachment_test_msg.msg"); - msgEmbMsg = getFileAndCheck(olTests, "attachment_msg_pdf.msg"); - } + POIDataSamples ssTests = POIDataSamples.getSpreadSheetInstance(); + xls = getFileAndCheck(ssTests, "SampleSS.xls"); + xlsx = getFileAndCheck(ssTests, "SampleSS.xlsx"); + xlsxStrict = getFileAndCheck(ssTests, "SampleSS.strict.xlsx"); + xltx = getFileAndCheck(ssTests, "test.xltx"); + xlsEmb = getFileAndCheck(ssTests, "excel_with_embeded.xls"); - public void testFile() throws Exception { - // Excel - POITextExtractor xlsExtractor = ExtractorFactory.createExtractor(xls); - assertNotNull("Had empty extractor for " + xls, xlsExtractor); - assertTrue("Expected instanceof ExcelExtractor, but had: " + xlsExtractor.getClass(), - xlsExtractor - instanceof ExcelExtractor - ); - assertTrue( - xlsExtractor.getText().length() > 200 - ); - xlsExtractor.close(); + POIDataSamples wpTests = POIDataSamples.getDocumentInstance(); + doc = getFileAndCheck(wpTests, "SampleDoc.doc"); + doc6 = getFileAndCheck(wpTests, "Word6.doc"); + doc95 = getFileAndCheck(wpTests, "Word95.doc"); + docx = getFileAndCheck(wpTests, "SampleDoc.docx"); + dotx = getFileAndCheck(wpTests, "test.dotx"); + docEmb = getFileAndCheck(wpTests, "word_with_embeded.doc"); + docEmbOOXML = getFileAndCheck(wpTests, "word_with_embeded_ooxml.doc"); - POITextExtractor extractor = ExtractorFactory.createExtractor(xlsx); - assertTrue( - extractor - instanceof XSSFExcelExtractor - ); - extractor.close(); + POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); + ppt = getFileAndCheck(slTests, "SampleShow.ppt"); + pptx = getFileAndCheck(slTests, "SampleShow.pptx"); + txt = getFileAndCheck(slTests, "SampleShow.txt"); - extractor = ExtractorFactory.createExtractor(xlsx); - assertTrue( - extractor.getText().length() > 200 - ); - extractor.close(); + POIDataSamples dgTests = POIDataSamples.getDiagramInstance(); + vsd = getFileAndCheck(dgTests, "Test_Visio-Some_Random_Text.vsd"); + vsdx = getFileAndCheck(dgTests, "test.vsdx"); - extractor = ExtractorFactory.createExtractor(xltx); - assertTrue( - extractor - instanceof XSSFExcelExtractor - ); - extractor.close(); + POIDataSamples pubTests = POIDataSamples.getPublisherInstance(); + pub = getFileAndCheck(pubTests, "Simple.pub"); - extractor = ExtractorFactory.createExtractor(xltx); - assertTrue( - extractor.getText().contains("test") - ); - extractor.close(); + POIDataSamples olTests = POIDataSamples.getHSMFInstance(); + msg = getFileAndCheck(olTests, "quick.msg"); + msgEmb = getFileAndCheck(olTests, "attachment_test_msg.msg"); + msgEmbMsg = getFileAndCheck(olTests, "attachment_msg_pdf.msg"); + } + + public void testFile() throws Exception { + // Excel + POITextExtractor xlsExtractor = ExtractorFactory.createExtractor(xls); + assertNotNull("Had empty extractor for " + xls, xlsExtractor); + assertTrue("Expected instanceof ExcelExtractor, but had: " + xlsExtractor.getClass(), + xlsExtractor + instanceof ExcelExtractor + ); + assertTrue( + xlsExtractor.getText().length() > 200 + ); + xlsExtractor.close(); + + POITextExtractor extractor = ExtractorFactory.createExtractor(xlsx); + assertTrue( + extractor + instanceof XSSFExcelExtractor + ); + extractor.close(); + + extractor = ExtractorFactory.createExtractor(xlsx); + assertTrue( + extractor.getText().length() > 200 + ); + extractor.close(); + + extractor = ExtractorFactory.createExtractor(xltx); + assertTrue( + extractor + instanceof XSSFExcelExtractor + ); + extractor.close(); + + extractor = ExtractorFactory.createExtractor(xltx); + assertTrue( + extractor.getText().contains("test") + ); + extractor.close(); + + // TODO Support OOXML-Strict, see bug #57699 + try { + extractor = ExtractorFactory.createExtractor(xlsxStrict); + fail("OOXML-Strict isn't yet supported"); + } catch (POIXMLException e) { + // Expected, for now + } +// extractor = ExtractorFactory.createExtractor(xlsxStrict); +// assertTrue( +// extractor +// instanceof XSSFExcelExtractor +// ); +// extractor.close(); +// +// extractor = ExtractorFactory.createExtractor(xlsxStrict); +// assertTrue( +// extractor.getText().contains("test") +// ); +// extractor.close(); - // Word - assertTrue( - ExtractorFactory.createExtractor(doc) - instanceof WordExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(doc).getText().length() > 120 - ); + // Word + assertTrue( + ExtractorFactory.createExtractor(doc) + instanceof WordExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(doc).getText().length() > 120 + ); - assertTrue( - ExtractorFactory.createExtractor(doc6) - instanceof Word6Extractor - ); - assertTrue( - ExtractorFactory.createExtractor(doc6).getText().length() > 20 - ); - - assertTrue( - ExtractorFactory.createExtractor(doc95) - instanceof Word6Extractor - ); - assertTrue( - ExtractorFactory.createExtractor(doc95).getText().length() > 120 - ); - - extractor = ExtractorFactory.createExtractor(docx); - assertTrue( - extractor instanceof XWPFWordExtractor - ); - extractor.close(); - - extractor = ExtractorFactory.createExtractor(docx); - assertTrue( - extractor.getText().length() > 120 - ); - extractor.close(); + assertTrue( + ExtractorFactory.createExtractor(doc6) + instanceof Word6Extractor + ); + assertTrue( + ExtractorFactory.createExtractor(doc6).getText().length() > 20 + ); - extractor = ExtractorFactory.createExtractor(dotx); - assertTrue( - extractor instanceof XWPFWordExtractor - ); - extractor.close(); - - extractor = ExtractorFactory.createExtractor(dotx); - assertTrue( - extractor.getText().contains("Test") - ); - extractor.close(); + assertTrue( + ExtractorFactory.createExtractor(doc95) + instanceof Word6Extractor + ); + assertTrue( + ExtractorFactory.createExtractor(doc95).getText().length() > 120 + ); - // PowerPoint - assertTrue( - ExtractorFactory.createExtractor(ppt) - instanceof PowerPointExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(ppt).getText().length() > 120 - ); + extractor = ExtractorFactory.createExtractor(docx); + assertTrue( + extractor instanceof XWPFWordExtractor + ); + extractor.close(); - extractor = ExtractorFactory.createExtractor(pptx); - assertTrue( - extractor - instanceof XSLFPowerPointExtractor - ); - extractor.close(); + extractor = ExtractorFactory.createExtractor(docx); + assertTrue( + extractor.getText().length() > 120 + ); + extractor.close(); - extractor = ExtractorFactory.createExtractor(pptx); - assertTrue( - extractor.getText().length() > 120 - ); - extractor.close(); + extractor = ExtractorFactory.createExtractor(dotx); + assertTrue( + extractor instanceof XWPFWordExtractor + ); + extractor.close(); - // Visio - assertTrue( - ExtractorFactory.createExtractor(vsd) - instanceof VisioTextExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(vsd).getText().length() > 50 - ); - - // Publisher - assertTrue( - ExtractorFactory.createExtractor(pub) - instanceof PublisherTextExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(pub).getText().length() > 50 - ); - - // Outlook msg - assertTrue( - ExtractorFactory.createExtractor(msg) - instanceof OutlookTextExtactor - ); - assertTrue( - ExtractorFactory.createExtractor(msg).getText().length() > 50 - ); + extractor = ExtractorFactory.createExtractor(dotx); + assertTrue( + extractor.getText().contains("Test") + ); + extractor.close(); + + // PowerPoint + assertTrue( + ExtractorFactory.createExtractor(ppt) + instanceof PowerPointExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(ppt).getText().length() > 120 + ); + + extractor = ExtractorFactory.createExtractor(pptx); + assertTrue( + extractor + instanceof XSLFPowerPointExtractor + ); + extractor.close(); + + extractor = ExtractorFactory.createExtractor(pptx); + assertTrue( + extractor.getText().length() > 120 + ); + extractor.close(); + + // Visio - binary + assertTrue( + ExtractorFactory.createExtractor(vsd) + instanceof VisioTextExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(vsd).getText().length() > 50 + ); + // Visio - vsdx + try { + ExtractorFactory.createExtractor(vsdx); + fail(); + } catch(IllegalArgumentException e) { + // Good + } + + // Publisher + assertTrue( + ExtractorFactory.createExtractor(pub) + instanceof PublisherTextExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(pub).getText().length() > 50 + ); + + // Outlook msg + assertTrue( + ExtractorFactory.createExtractor(msg) + instanceof OutlookTextExtactor + ); + assertTrue( + ExtractorFactory.createExtractor(msg).getText().length() > 50 + ); + + // Text + try { + ExtractorFactory.createExtractor(txt); + fail(); + } catch(IllegalArgumentException e) { + // Good + } + } + + public void testInputStream() throws Exception { + // Excel + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(xls)) + instanceof ExcelExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(xls)).getText().length() > 200 + ); + + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(xlsx)) + instanceof XSSFExcelExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(xlsx)).getText().length() > 200 + ); + // TODO Support OOXML-Strict, see bug #57699 +// assertTrue( +// ExtractorFactory.createExtractor(new FileInputStream(xlsxStrict)) +// instanceof XSSFExcelExtractor +// ); +// assertTrue( +// ExtractorFactory.createExtractor(new FileInputStream(xlsxStrict)).getText().length() > 200 +// ); + + // Word + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(doc)) + instanceof WordExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(doc)).getText().length() > 120 + ); - // Text - try { - ExtractorFactory.createExtractor(txt); - fail(); - } catch(IllegalArgumentException e) { - // Good - } - } - - public void testInputStream() throws Exception { - // Excel - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(xls)) - instanceof ExcelExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(xls)).getText().length() > 200 - ); - - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(xlsx)) - instanceof XSSFExcelExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(xlsx)).getText().length() > 200 - ); - - // Word - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(doc)) - instanceof WordExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(doc)).getText().length() > 120 - ); - assertTrue( ExtractorFactory.createExtractor(new FileInputStream(doc6)) instanceof Word6Extractor @@ -300,7 +339,7 @@ public class TestExtractorFactory extends TestCase { assertTrue( ExtractorFactory.createExtractor(new FileInputStream(doc6)).getText().length() > 20 ); - + assertTrue( ExtractorFactory.createExtractor(new FileInputStream(doc95)) instanceof Word6Extractor @@ -308,92 +347,99 @@ public class TestExtractorFactory extends TestCase { assertTrue( ExtractorFactory.createExtractor(new FileInputStream(doc95)).getText().length() > 120 ); - - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(docx)) - instanceof XWPFWordExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(docx)).getText().length() > 120 - ); - - // PowerPoint - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(ppt)) - instanceof PowerPointExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(ppt)).getText().length() > 120 - ); - - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(pptx)) - instanceof XSLFPowerPointExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(pptx)).getText().length() > 120 - ); - - // Visio - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(vsd)) - instanceof VisioTextExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(vsd)).getText().length() > 50 - ); - - // Publisher - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(pub)) - instanceof PublisherTextExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(pub)).getText().length() > 50 - ); - - // Outlook msg - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(msg)) - instanceof OutlookTextExtactor - ); - assertTrue( - ExtractorFactory.createExtractor(new FileInputStream(msg)).getText().length() > 50 - ); - - // Text - try { - FileInputStream stream = new FileInputStream(txt); - try { + + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(docx)) + instanceof XWPFWordExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(docx)).getText().length() > 120 + ); + + // PowerPoint + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(ppt)) + instanceof PowerPointExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(ppt)).getText().length() > 120 + ); + + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(pptx)) + instanceof XSLFPowerPointExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(pptx)).getText().length() > 120 + ); + + // Visio + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(vsd)) + instanceof VisioTextExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(vsd)).getText().length() > 50 + ); + // Visio - vsdx + try { + ExtractorFactory.createExtractor(new FileInputStream(vsdx)); + fail(); + } catch(IllegalArgumentException e) { + // Good + } + + // Publisher + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(pub)) + instanceof PublisherTextExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(pub)).getText().length() > 50 + ); + + // Outlook msg + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(msg)) + instanceof OutlookTextExtactor + ); + assertTrue( + ExtractorFactory.createExtractor(new FileInputStream(msg)).getText().length() > 50 + ); + + // Text + try { + FileInputStream stream = new FileInputStream(txt); + try { ExtractorFactory.createExtractor(stream); - fail(); - } finally { - stream.close(); - } - } catch(IllegalArgumentException e) { - // Good - } - } - - public void testPOIFS() throws Exception { - // Excel - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))) - instanceof ExcelExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))).getText().length() > 200 - ); - - // Word - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(doc))) - instanceof WordExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(doc))).getText().length() > 120 - ); - + fail(); + } finally { + stream.close(); + } + } catch(IllegalArgumentException e) { + // Good + } + } + + public void testPOIFS() throws Exception { + // Excel + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))) + instanceof ExcelExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))).getText().length() > 200 + ); + + // Word + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(doc))) + instanceof WordExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(doc))).getText().length() > 120 + ); + assertTrue( ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(doc6))) instanceof Word6Extractor @@ -401,7 +447,7 @@ public class TestExtractorFactory extends TestCase { assertTrue( ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(doc6))).getText().length() > 20 ); - + assertTrue( ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(doc95))) instanceof Word6Extractor @@ -409,297 +455,297 @@ public class TestExtractorFactory extends TestCase { assertTrue( ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(doc95))).getText().length() > 120 ); - - // PowerPoint - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(ppt))) - instanceof PowerPointExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(ppt))).getText().length() > 120 - ); - - // Visio - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(vsd))) - instanceof VisioTextExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(vsd))).getText().length() > 50 - ); - - // Publisher - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(pub))) - instanceof PublisherTextExtractor - ); - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(pub))).getText().length() > 50 - ); - - // Outlook msg - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(msg))) - instanceof OutlookTextExtactor - ); - assertTrue( - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(msg))).getText().length() > 50 - ); - - // Text - try { - ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(txt))); - fail(); - } catch(IOException e) { - // Good - } - } - - public void testPackage() throws Exception { - // Excel - POIXMLTextExtractor extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString(), PackageAccess.READ)); + + // PowerPoint assertTrue( - extractor - instanceof XSSFExcelExtractor - ); + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(ppt))) + instanceof PowerPointExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(ppt))).getText().length() > 120 + ); + + // Visio + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(vsd))) + instanceof VisioTextExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(vsd))).getText().length() > 50 + ); + + // Publisher + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(pub))) + instanceof PublisherTextExtractor + ); + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(pub))).getText().length() > 50 + ); + + // Outlook msg + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(msg))) + instanceof OutlookTextExtactor + ); + assertTrue( + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(msg))).getText().length() > 50 + ); + + // Text + try { + ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(txt))); + fail(); + } catch(IOException e) { + // Good + } + } + + public void testPackage() throws Exception { + // Excel + POIXMLTextExtractor extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString(), PackageAccess.READ)); + assertTrue( + extractor + instanceof XSSFExcelExtractor + ); extractor.close(); - extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString())); + extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString())); assertTrue(extractor.getText().length() > 200); extractor.close(); - - // Word - extractor = ExtractorFactory.createExtractor(OPCPackage.open(docx.toString())); + + // Word + extractor = ExtractorFactory.createExtractor(OPCPackage.open(docx.toString())); assertTrue( - extractor - instanceof XWPFWordExtractor - ); - extractor.close(); - - extractor = ExtractorFactory.createExtractor(OPCPackage.open(docx.toString())); - assertTrue( - extractor.getText().length() > 120 - ); - extractor.close(); - - // PowerPoint - extractor = ExtractorFactory.createExtractor(OPCPackage.open(pptx.toString())); - assertTrue( - extractor - instanceof XSLFPowerPointExtractor - ); + extractor + instanceof XWPFWordExtractor + ); extractor.close(); - extractor = ExtractorFactory.createExtractor(OPCPackage.open(pptx.toString())); + extractor = ExtractorFactory.createExtractor(OPCPackage.open(docx.toString())); assertTrue( - extractor.getText().length() > 120 - ); + extractor.getText().length() > 120 + ); extractor.close(); - - // Text - try { - ExtractorFactory.createExtractor(OPCPackage.open(txt.toString())); - fail(); - } catch(InvalidOperationException e) { - // Good - } - } - - public void testPreferEventBased() throws Exception { - assertFalse(ExtractorFactory.getPreferEventExtractor()); - assertFalse(ExtractorFactory.getThreadPrefersEventExtractors()); - assertNull(ExtractorFactory.getAllThreadsPreferEventExtractors()); - - ExtractorFactory.setThreadPrefersEventExtractors(true); - - assertTrue(ExtractorFactory.getPreferEventExtractor()); - assertTrue(ExtractorFactory.getThreadPrefersEventExtractors()); - assertNull(ExtractorFactory.getAllThreadsPreferEventExtractors()); - - ExtractorFactory.setAllThreadsPreferEventExtractors(false); - - assertFalse(ExtractorFactory.getPreferEventExtractor()); - assertTrue(ExtractorFactory.getThreadPrefersEventExtractors()); - assertEquals(Boolean.FALSE, ExtractorFactory.getAllThreadsPreferEventExtractors()); - - ExtractorFactory.setAllThreadsPreferEventExtractors(null); - - assertTrue(ExtractorFactory.getPreferEventExtractor()); - assertTrue(ExtractorFactory.getThreadPrefersEventExtractors()); - assertNull(ExtractorFactory.getAllThreadsPreferEventExtractors()); - - - // Check we get the right extractors now - POITextExtractor extractor = ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))); - assertTrue( - extractor - instanceof EventBasedExcelExtractor - ); - extractor.close(); - extractor = ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))); - assertTrue( - extractor.getText().length() > 200 - ); - extractor.close(); - - extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString(), PackageAccess.READ)); - assertTrue(extractor instanceof XSSFEventBasedExcelExtractor); - extractor.close(); - extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString(), PackageAccess.READ)); - assertTrue( - extractor.getText().length() > 200 - ); - extractor.close(); - - - // Put back to normal - ExtractorFactory.setThreadPrefersEventExtractors(false); - assertFalse(ExtractorFactory.getPreferEventExtractor()); - assertFalse(ExtractorFactory.getThreadPrefersEventExtractors()); - assertNull(ExtractorFactory.getAllThreadsPreferEventExtractors()); - - // And back - extractor = ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))); - assertTrue( - extractor - instanceof ExcelExtractor - ); - extractor.close(); - extractor = ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))); - assertTrue( - extractor.getText().length() > 200 - ); - extractor.close(); - - extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString(), PackageAccess.READ)); - assertTrue( - extractor - instanceof XSSFExcelExtractor - ); - extractor.close(); - extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString())); - assertTrue( - extractor.getText().length() > 200 - ); - extractor.close(); - } + // PowerPoint + extractor = ExtractorFactory.createExtractor(OPCPackage.open(pptx.toString())); + assertTrue( + extractor + instanceof XSLFPowerPointExtractor + ); + extractor.close(); - /** - * Test embeded docs text extraction. For now, only - * does poifs embeded, but will do ooxml ones - * at some point. - */ - public void testEmbeded() throws Exception { - POIOLE2TextExtractor ext; - POITextExtractor[] embeds; + extractor = ExtractorFactory.createExtractor(OPCPackage.open(pptx.toString())); + assertTrue( + extractor.getText().length() > 120 + ); + extractor.close(); - // No embedings - ext = (POIOLE2TextExtractor) - ExtractorFactory.createExtractor(xls); - embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); - assertEquals(0, embeds.length); + // Text + try { + ExtractorFactory.createExtractor(OPCPackage.open(txt.toString())); + fail(); + } catch(InvalidOperationException e) { + // Good + } + } - // Excel - ext = (POIOLE2TextExtractor) - ExtractorFactory.createExtractor(xlsEmb); - embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + public void testPreferEventBased() throws Exception { + assertFalse(ExtractorFactory.getPreferEventExtractor()); + assertFalse(ExtractorFactory.getThreadPrefersEventExtractors()); + assertNull(ExtractorFactory.getAllThreadsPreferEventExtractors()); - assertEquals(6, embeds.length); - int numWord = 0, numXls = 0, numPpt = 0, numMsg = 0, numWordX; - for(int i=0; i 20); + ExtractorFactory.setThreadPrefersEventExtractors(true); - if(embeds[i] instanceof PowerPointExtractor) numPpt++; - else if(embeds[i] instanceof ExcelExtractor) numXls++; - else if(embeds[i] instanceof WordExtractor) numWord++; - else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; - } - assertEquals(2, numPpt); - assertEquals(2, numXls); - assertEquals(2, numWord); - assertEquals(0, numMsg); + assertTrue(ExtractorFactory.getPreferEventExtractor()); + assertTrue(ExtractorFactory.getThreadPrefersEventExtractors()); + assertNull(ExtractorFactory.getAllThreadsPreferEventExtractors()); - // Word - ext = (POIOLE2TextExtractor) - ExtractorFactory.createExtractor(docEmb); - embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + ExtractorFactory.setAllThreadsPreferEventExtractors(false); - numWord = 0; numXls = 0; numPpt = 0; numMsg = 0; - assertEquals(4, embeds.length); - for(int i=0; i 20); - if(embeds[i] instanceof PowerPointExtractor) numPpt++; - else if(embeds[i] instanceof ExcelExtractor) numXls++; - else if(embeds[i] instanceof WordExtractor) numWord++; - else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; - } - assertEquals(1, numPpt); - assertEquals(2, numXls); - assertEquals(1, numWord); - assertEquals(0, numMsg); - - // Word which contains an OOXML file - ext = (POIOLE2TextExtractor) - ExtractorFactory.createExtractor(docEmbOOXML); - embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + assertFalse(ExtractorFactory.getPreferEventExtractor()); + assertTrue(ExtractorFactory.getThreadPrefersEventExtractors()); + assertEquals(Boolean.FALSE, ExtractorFactory.getAllThreadsPreferEventExtractors()); - numWord = 0; numXls = 0; numPpt = 0; numMsg = 0; numWordX = 0; - assertEquals(3, embeds.length); - for(int i=0; i 20); - if(embeds[i] instanceof PowerPointExtractor) numPpt++; - else if(embeds[i] instanceof ExcelExtractor) numXls++; - else if(embeds[i] instanceof WordExtractor) numWord++; - else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; - else if(embeds[i] instanceof XWPFWordExtractor) numWordX++; - } - assertEquals(1, numPpt); - assertEquals(1, numXls); - assertEquals(0, numWord); - assertEquals(1, numWordX); - assertEquals(0, numMsg); - - // Outlook - ext = (OutlookTextExtactor) - ExtractorFactory.createExtractor(msgEmb); - embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + ExtractorFactory.setAllThreadsPreferEventExtractors(null); - numWord = 0; numXls = 0; numPpt = 0; numMsg = 0; - assertEquals(1, embeds.length); - for(int i=0; i 20); - if(embeds[i] instanceof PowerPointExtractor) numPpt++; - else if(embeds[i] instanceof ExcelExtractor) numXls++; - else if(embeds[i] instanceof WordExtractor) numWord++; - else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; - } - assertEquals(0, numPpt); - assertEquals(0, numXls); - assertEquals(1, numWord); - assertEquals(0, numMsg); - - // Outlook with another outlook file in it - ext = (OutlookTextExtactor) - ExtractorFactory.createExtractor(msgEmbMsg); - embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + assertTrue(ExtractorFactory.getPreferEventExtractor()); + assertTrue(ExtractorFactory.getThreadPrefersEventExtractors()); + assertNull(ExtractorFactory.getAllThreadsPreferEventExtractors()); - numWord = 0; numXls = 0; numPpt = 0; numMsg = 0; - assertEquals(1, embeds.length); - for(int i=0; i 20); - if(embeds[i] instanceof PowerPointExtractor) numPpt++; - else if(embeds[i] instanceof ExcelExtractor) numXls++; - else if(embeds[i] instanceof WordExtractor) numWord++; - else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; - } - assertEquals(0, numPpt); - assertEquals(0, numXls); - assertEquals(0, numWord); - assertEquals(1, numMsg); - - // TODO - PowerPoint - // TODO - Publisher - // TODO - Visio - } + // Check we get the right extractors now + POITextExtractor extractor = ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))); + assertTrue( + extractor + instanceof EventBasedExcelExtractor + ); + extractor.close(); + extractor = ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))); + assertTrue( + extractor.getText().length() > 200 + ); + extractor.close(); + + extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString(), PackageAccess.READ)); + assertTrue(extractor instanceof XSSFEventBasedExcelExtractor); + extractor.close(); + + extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString(), PackageAccess.READ)); + assertTrue( + extractor.getText().length() > 200 + ); + extractor.close(); + + + // Put back to normal + ExtractorFactory.setThreadPrefersEventExtractors(false); + assertFalse(ExtractorFactory.getPreferEventExtractor()); + assertFalse(ExtractorFactory.getThreadPrefersEventExtractors()); + assertNull(ExtractorFactory.getAllThreadsPreferEventExtractors()); + + // And back + extractor = ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))); + assertTrue( + extractor + instanceof ExcelExtractor + ); + extractor.close(); + extractor = ExtractorFactory.createExtractor(new POIFSFileSystem(new FileInputStream(xls))); + assertTrue( + extractor.getText().length() > 200 + ); + extractor.close(); + + extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString(), PackageAccess.READ)); + assertTrue( + extractor + instanceof XSSFExcelExtractor + ); + extractor.close(); + extractor = ExtractorFactory.createExtractor(OPCPackage.open(xlsx.toString())); + assertTrue( + extractor.getText().length() > 200 + ); + extractor.close(); + } + + /** + * Test embeded docs text extraction. For now, only + * does poifs embeded, but will do ooxml ones + * at some point. + */ + public void testEmbeded() throws Exception { + POIOLE2TextExtractor ext; + POITextExtractor[] embeds; + + // No embedings + ext = (POIOLE2TextExtractor) + ExtractorFactory.createExtractor(xls); + embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + assertEquals(0, embeds.length); + + // Excel + ext = (POIOLE2TextExtractor) + ExtractorFactory.createExtractor(xlsEmb); + embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + + assertEquals(6, embeds.length); + int numWord = 0, numXls = 0, numPpt = 0, numMsg = 0, numWordX; + for(int i=0; i 20); + + if(embeds[i] instanceof PowerPointExtractor) numPpt++; + else if(embeds[i] instanceof ExcelExtractor) numXls++; + else if(embeds[i] instanceof WordExtractor) numWord++; + else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; + } + assertEquals(2, numPpt); + assertEquals(2, numXls); + assertEquals(2, numWord); + assertEquals(0, numMsg); + + // Word + ext = (POIOLE2TextExtractor) + ExtractorFactory.createExtractor(docEmb); + embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + + numWord = 0; numXls = 0; numPpt = 0; numMsg = 0; + assertEquals(4, embeds.length); + for(int i=0; i 20); + if(embeds[i] instanceof PowerPointExtractor) numPpt++; + else if(embeds[i] instanceof ExcelExtractor) numXls++; + else if(embeds[i] instanceof WordExtractor) numWord++; + else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; + } + assertEquals(1, numPpt); + assertEquals(2, numXls); + assertEquals(1, numWord); + assertEquals(0, numMsg); + + // Word which contains an OOXML file + ext = (POIOLE2TextExtractor) + ExtractorFactory.createExtractor(docEmbOOXML); + embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + + numWord = 0; numXls = 0; numPpt = 0; numMsg = 0; numWordX = 0; + assertEquals(3, embeds.length); + for(int i=0; i 20); + if(embeds[i] instanceof PowerPointExtractor) numPpt++; + else if(embeds[i] instanceof ExcelExtractor) numXls++; + else if(embeds[i] instanceof WordExtractor) numWord++; + else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; + else if(embeds[i] instanceof XWPFWordExtractor) numWordX++; + } + assertEquals(1, numPpt); + assertEquals(1, numXls); + assertEquals(0, numWord); + assertEquals(1, numWordX); + assertEquals(0, numMsg); + + // Outlook + ext = (OutlookTextExtactor) + ExtractorFactory.createExtractor(msgEmb); + embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + + numWord = 0; numXls = 0; numPpt = 0; numMsg = 0; + assertEquals(1, embeds.length); + for(int i=0; i 20); + if(embeds[i] instanceof PowerPointExtractor) numPpt++; + else if(embeds[i] instanceof ExcelExtractor) numXls++; + else if(embeds[i] instanceof WordExtractor) numWord++; + else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; + } + assertEquals(0, numPpt); + assertEquals(0, numXls); + assertEquals(1, numWord); + assertEquals(0, numMsg); + + // Outlook with another outlook file in it + ext = (OutlookTextExtactor) + ExtractorFactory.createExtractor(msgEmbMsg); + embeds = ExtractorFactory.getEmbededDocsTextExtractors(ext); + + numWord = 0; numXls = 0; numPpt = 0; numMsg = 0; + assertEquals(1, embeds.length); + for(int i=0; i 20); + if(embeds[i] instanceof PowerPointExtractor) numPpt++; + else if(embeds[i] instanceof ExcelExtractor) numXls++; + else if(embeds[i] instanceof WordExtractor) numWord++; + else if(embeds[i] instanceof OutlookTextExtactor) numMsg++; + } + assertEquals(0, numPpt); + assertEquals(0, numXls); + assertEquals(0, numWord); + assertEquals(1, numMsg); + + + // TODO - PowerPoint + // TODO - Publisher + // TODO - Visio + } } diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/AllOpenXML4JTests.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/AllOpenXML4JTests.java index 1dcf93a32..a1a3ccc88 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/AllOpenXML4JTests.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/AllOpenXML4JTests.java @@ -17,28 +17,24 @@ package org.apache.poi.openxml4j.opc; -import junit.framework.Test; -import junit.framework.TestSuite; - import org.apache.poi.openxml4j.opc.compliance.AllOpenXML4JComplianceTests; import org.apache.poi.openxml4j.opc.internal.AllOpenXML4JInternalTests; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestContentType.class + , TestFileHelper.class + , TestListParts.class + , TestPackage.class + , TestPackageCoreProperties.class + , TestPackagePartName.class + , TestPackageThumbnail.class + , TestPackagingURIHelper.class + , TestRelationships.class + , AllOpenXML4JComplianceTests.class + , AllOpenXML4JInternalTests.class +}) public final class AllOpenXML4JTests { - - public static Test suite() { - - TestSuite suite = new TestSuite(AllOpenXML4JTests.class.getName()); - suite.addTestSuite(TestContentType.class); - suite.addTestSuite(TestFileHelper.class); - suite.addTestSuite(TestListParts.class); - suite.addTestSuite(TestPackage.class); - suite.addTestSuite(TestPackageCoreProperties.class); - suite.addTestSuite(TestPackagePartName.class); - suite.addTestSuite(TestPackageThumbnail.class); - suite.addTestSuite(TestPackagingURIHelper.class); - suite.addTestSuite(TestRelationships.class); - suite.addTest(AllOpenXML4JComplianceTests.suite()); - suite.addTest(AllOpenXML4JInternalTests.suite()); - return suite; - } } diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java index 07a2b333d..a6955958f 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java @@ -17,6 +17,14 @@ package org.apache.poi.openxml4j.opc; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -25,35 +33,47 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.net.URI; +import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.TreeMap; import java.util.regex.Pattern; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; -import junit.framework.TestCase; - +import org.apache.poi.POIXMLException; import org.apache.poi.openxml4j.OpenXML4JTestDataSamples; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; import org.apache.poi.openxml4j.opc.internal.FileHelper; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; +import org.apache.poi.openxml4j.opc.internal.ZipHelper; +import org.apache.poi.openxml4j.util.ZipSecureFile; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.util.DocumentHelper; +import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.TempFile; +import org.junit.Ignore; +import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; -public final class TestPackage extends TestCase { +public final class TestPackage { private static final POILogger logger = POILogFactory.getLogger(TestPackage.class); /** * Test that just opening and closing the file doesn't alter the document. */ - public void testOpenSave() throws Exception { + @Test + public void openSave() throws Exception { String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageOpenSaveTMP.docx"); @@ -75,7 +95,8 @@ public final class TestPackage extends TestCase { * Test that when we create a new Package, we give it * the correct default content types */ - public void testCreateGetsContentTypes() throws Exception { + @Test + public void createGetsContentTypes() throws Exception { File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageTMP.docx"); // Zap the target file, in case of an earlier run @@ -107,7 +128,8 @@ public final class TestPackage extends TestCase { /** * Test package creation. */ - public void testCreatePackageAddPart() throws Exception { + @Test + public void createPackageAddPart() throws Exception { File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestCreatePackageTMP.docx"); File expectedFile = OpenXML4JTestDataSamples.getSampleFile("TestCreatePackageOUTPUT.docx"); @@ -153,7 +175,8 @@ public final class TestPackage extends TestCase { * document and another part, save and re-load and * have everything setup as expected */ - public void testCreatePackageWithCoreDocument() throws Exception { + @Test + public void createPackageWithCoreDocument() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); OPCPackage pkg = OPCPackage.create(baos); @@ -247,7 +270,8 @@ public final class TestPackage extends TestCase { /** * Test package opening. */ - public void testOpenPackage() throws Exception { + @Test + public void openPackage() throws Exception { File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestOpenPackageTMP.docx"); File inputFile = OpenXML4JTestDataSamples.getSampleFile("TestOpenPackageINPUT.docx"); @@ -306,7 +330,8 @@ public final class TestPackage extends TestCase { * OutputStream, in addition to the normal writing * to a file */ - public void testSaveToOutputStream() throws Exception { + @Test + public void saveToOutputStream() throws Exception { String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageOpenSaveTMP.docx"); @@ -334,7 +359,8 @@ public final class TestPackage extends TestCase { * simple InputStream, in addition to the normal * reading from a file */ - public void testOpenFromInputStream() throws Exception { + @Test + public void openFromInputStream() throws Exception { String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); FileInputStream finp = new FileInputStream(originalFile); @@ -353,7 +379,9 @@ public final class TestPackage extends TestCase { /** * TODO: fix and enable */ - public void disabled_testRemovePartRecursive() throws Exception { + @Test + @Ignore + public void removePartRecursive() throws Exception { String originalFile = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCommon.docx"); File targetFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageRemovePartRecursiveOUTPUT.docx"); File tempFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageRemovePartRecursiveTMP.docx"); @@ -369,7 +397,8 @@ public final class TestPackage extends TestCase { assertTrue(targetFile.delete()); } - public void testDeletePart() throws InvalidFormatException { + @Test + public void deletePart() throws InvalidFormatException { TreeMap expectedValues; TreeMap values; @@ -426,7 +455,8 @@ public final class TestPackage extends TestCase { p.revert(); } - public void testDeletePartRecursive() throws InvalidFormatException { + @Test + public void deletePartRecursive() throws InvalidFormatException { TreeMap expectedValues; TreeMap values; @@ -468,7 +498,8 @@ public final class TestPackage extends TestCase { * Test that we can open a file by path, and then * write changes to it. */ - public void testOpenFileThenOverwrite() throws Exception { + @Test + public void openFileThenOverwrite() throws Exception { File tempFile = TempFile.createTempFile("poiTesting","tmp"); File origFile = OpenXML4JTestDataSamples.getSampleFile("TestPackageCommon.docx"); FileHelper.copyFile(origFile, tempFile); @@ -505,7 +536,8 @@ public final class TestPackage extends TestCase { * Test that we can open a file by path, save it * to another file, then delete both */ - public void testOpenFileThenSaveDelete() throws Exception { + @Test + public void openFileThenSaveDelete() throws Exception { File tempFile = TempFile.createTempFile("poiTesting","tmp"); File tempFile2 = TempFile.createTempFile("poiTesting","tmp"); File origFile = OpenXML4JTestDataSamples.getSampleFile("TestPackageCommon.docx"); @@ -529,7 +561,8 @@ public final class TestPackage extends TestCase { return (ContentTypeManager)f.get(pkg); } - public void testGetPartsByName() throws Exception { + @Test + public void getPartsByName() throws Exception { String filepath = OpenXML4JTestDataSamples.getSampleFileName("sample.docx"); OPCPackage pkg = OPCPackage.open(filepath, PackageAccess.READ_WRITE); @@ -553,7 +586,8 @@ public final class TestPackage extends TestCase { } } - public void testGetPartSize() throws Exception { + @Test + public void getPartSize() throws Exception { String filepath = OpenXML4JTestDataSamples.getSampleFileName("sample.docx"); OPCPackage pkg = OPCPackage.open(filepath, PackageAccess.READ); try { @@ -585,7 +619,8 @@ public final class TestPackage extends TestCase { } } - public void testReplaceContentType() throws Exception { + @Test + public void replaceContentType() throws Exception { InputStream is = OpenXML4JTestDataSamples.openSampleStream("sample.xlsx"); OPCPackage p = OPCPackage.open(is); @@ -603,4 +638,131 @@ public final class TestPackage extends TestCase { assertFalse(mgr.isContentTypeRegister("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml")); assertTrue(mgr.isContentTypeRegister("application/vnd.ms-excel.sheet.macroEnabled.main+xml")); } + + @Test(expected=IOException.class) + public void zipBombCreateAndHandle() throws Exception { + // #50090 / #56865 + ZipFile zipFile = ZipHelper.openZipFile(OpenXML4JTestDataSamples.getSampleFile("sample.xlsx")); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ZipOutputStream append = new ZipOutputStream(bos); + // first, copy contents from existing war + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry e2 = entries.nextElement(); + ZipEntry e = new ZipEntry(e2.getName()); + e.setTime(e2.getTime()); + e.setComment(e2.getComment()); + e.setSize(e2.getSize()); + + append.putNextEntry(e); + if (!e.isDirectory()) { + InputStream is = zipFile.getInputStream(e); + if (e.getName().equals("[Content_Types].xml")) { + ByteArrayOutputStream bos2 = new ByteArrayOutputStream(); + IOUtils.copy(is, bos2); + long size = bos2.size()-"".length(); + append.write(bos2.toByteArray(), 0, (int)size); + byte spam[] = new byte[0x7FFF]; + for (int i=0; i".getBytes()); + size += 8; + e.setSize(size); + } else { + IOUtils.copy(is, append); + } + } + append.closeEntry(); + } + + append.close(); + zipFile.close(); + + byte buf[] = bos.toByteArray(); + bos = null; + + Workbook wb = WorkbookFactory.create(new ByteArrayInputStream(buf)); + wb.getSheetAt(0); + wb.close(); + } + + @Test + public void zipBombCheckSizes() throws Exception { + File file = OpenXML4JTestDataSamples.getSampleFile("sample.xlsx"); + + try { + double min_ratio = Double.MAX_VALUE; + long max_size = 0; + ZipFile zf = ZipHelper.openZipFile(file); + Enumeration entries = zf.entries(); + while (entries.hasMoreElements()) { + ZipEntry ze = entries.nextElement(); + double ratio = (double)ze.getCompressedSize() / (double)ze.getSize(); + min_ratio = Math.min(min_ratio, ratio); + max_size = Math.max(max_size, ze.getSize()); + } + zf.close(); + + // use values close to, but within the limits + ZipSecureFile.setMinInflateRatio(min_ratio-0.002); + ZipSecureFile.setMaxEntrySize(max_size+1); + Workbook wb = WorkbookFactory.create(file, null, true); + wb.close(); + + // check ratio out of bounds + ZipSecureFile.setMinInflateRatio(min_ratio+0.002); + try { + wb = WorkbookFactory.create(file, null, true); + wb.close(); + // this is a bit strange, as there will be different exceptions thrown + // depending if this executed via "ant test" or within eclipse + // maybe a difference in JDK ... + } catch (InvalidFormatException e) { + checkForZipBombException(e); + } catch (POIXMLException e) { + checkForZipBombException(e); + } + + // check max entry size ouf of bounds + ZipSecureFile.setMinInflateRatio(min_ratio-0.002); + ZipSecureFile.setMaxEntrySize(max_size-1); + try { + wb = WorkbookFactory.create(file, null, true); + wb.close(); + } catch (InvalidFormatException e) { + checkForZipBombException(e); + } catch (POIXMLException e) { + checkForZipBombException(e); + } + } finally { + // reset otherwise a lot of ooxml tests will fail + ZipSecureFile.setMinInflateRatio(0.01d); + ZipSecureFile.setMaxEntrySize(0xFFFFFFFFl); + } + } + + private void checkForZipBombException(Throwable e) { + if(e instanceof InvocationTargetException) { + InvocationTargetException t = (InvocationTargetException)e; + IOException t2 = (IOException)t.getTargetException(); + if("Zip bomb detected! Exiting.".equals(t2.getMessage())) { + return; + } + } + + if ("Zip bomb detected! Exiting.".equals(e.getMessage())) { + return; + } + + // recursively check the causes for the message as it can be nested further down in the exception-tree + if(e.getCause() != null && e.getCause() != e) { + checkForZipBombException(e.getCause()); + return; + } + + throw new IllegalStateException("Expected to catch an Exception because of a detected Zip Bomb, but did not find the related error message in the exception", e); + } } diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java index 0cf520009..b9517ba2e 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/compliance/TestOPCComplianceCoreProperties.java @@ -17,6 +17,10 @@ package org.apache.poi.openxml4j.opc.compliance; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; @@ -34,6 +38,8 @@ import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.util.IOUtils; +import org.apache.poi.util.TempFile; /** * Test core properties Open Packaging Convention compliance. @@ -224,4 +230,90 @@ public final class TestOPCComplianceCoreProperties extends TestCase { String msg = extractInvalidFormatMessage("LimitedXSITypeAttribute_PresentWithUnauthorizedValueFAIL.docx"); assertEquals("The element 'modified' must have the 'xsi:type' attribute with the value 'dcterms:W3CDTF' !", msg); } + + /** + * Document with no core properties - testing at the OPC level, + * saving into a new stream + */ + public void testNoCoreProperties_saveNew() throws Exception { + String sampleFileName = "OPCCompliance_NoCoreProperties.xlsx"; + OPCPackage pkg = OPCPackage.open(POIDataSamples.getOpenXML4JInstance().getFile(sampleFileName).getPath()); + + // Verify it has empty properties + assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(pkg.getPackageProperties()); + assertNotNull(pkg.getPackageProperties().getLanguageProperty()); + assertNull(pkg.getPackageProperties().getLanguageProperty().getValue()); + + // Save and re-load + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + pkg.save(baos); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + pkg = OPCPackage.open(bais); + + // An Empty Properties part has been added in the save/load + assertEquals(1, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(pkg.getPackageProperties()); + assertNotNull(pkg.getPackageProperties().getLanguageProperty()); + assertNull(pkg.getPackageProperties().getLanguageProperty().getValue()); + + + // Open a new copy of it + pkg = OPCPackage.open(POIDataSamples.getOpenXML4JInstance().getFile(sampleFileName).getPath()); + + // Save and re-load, without having touched the properties yet + baos = new ByteArrayOutputStream(); + pkg.save(baos); + bais = new ByteArrayInputStream(baos.toByteArray()); + pkg = OPCPackage.open(bais); + + // Check that this too added empty properties without error + assertEquals(1, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(pkg.getPackageProperties()); + assertNotNull(pkg.getPackageProperties().getLanguageProperty()); + assertNull(pkg.getPackageProperties().getLanguageProperty().getValue()); + } + + /** + * Document with no core properties - testing at the OPC level, + * from a temp-file, saving in-place + */ + public void testNoCoreProperties_saveInPlace() throws Exception { + String sampleFileName = "OPCCompliance_NoCoreProperties.xlsx"; + + // Copy this into a temp file, so we can play with it + File tmp = TempFile.createTempFile("poi-test", ".opc"); + FileOutputStream out = new FileOutputStream(tmp); + IOUtils.copy( + POIDataSamples.getOpenXML4JInstance().openResourceAsStream(sampleFileName), + out); + out.close(); + + // Open it from that temp file + OPCPackage pkg = OPCPackage.open(tmp); + + // Empty properties + assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(pkg.getPackageProperties()); + assertNotNull(pkg.getPackageProperties().getLanguageProperty()); + assertNull(pkg.getPackageProperties().getLanguageProperty().getValue()); + + // Save and close + pkg.close(); + + + // Re-open and check + pkg = OPCPackage.open(tmp); + + // An Empty Properties part has been added in the save/load + assertEquals(1, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(pkg.getPackageProperties()); + assertNotNull(pkg.getPackageProperties().getLanguageProperty()); + assertNull(pkg.getPackageProperties().getLanguageProperty().getValue()); + + // Finish and tidy + pkg.revert(); + tmp.delete(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java index 37deba5e8..fd494ba26 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestEncryptor.java @@ -18,6 +18,8 @@ package org.apache.poi.poifs.crypt; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; @@ -32,6 +34,8 @@ import java.util.Iterator; import javax.crypto.Cipher; import org.apache.poi.POIDataSamples; +import org.apache.poi.openxml4j.opc.ContentTypes; +import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.poifs.crypt.agile.AgileEncryptionHeader; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentNode; @@ -107,7 +111,7 @@ public class TestEncryptor { long decPackLenExpected = decExpected.getLength(); assertEquals(decPackLenExpected, payloadExpected.length); - is = nfs.getRoot().createDocumentInputStream("EncryptedPackage"); + is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY); is = new BoundedInputStream(is, is.available()-16); // ignore padding block byte encPackExpected[] = IOUtils.toByteArray(is); is.close(); @@ -159,7 +163,7 @@ public class TestEncryptor { long decPackLenActual = decActual.getLength(); - is = nfs.getRoot().createDocumentInputStream("EncryptedPackage"); + is = nfs.getRoot().createDocumentInputStream(Decryptor.DEFAULT_POIFS_ENTRY); is = new BoundedInputStream(is, is.available()-16); // ignore padding block byte encPackActual[] = IOUtils.toByteArray(is); is.close(); @@ -266,6 +270,55 @@ public class TestEncryptor { assertArrayEquals(payloadExpected, payloadActual); } + /** + * Ensure we can encrypt a package that is missing the Core + * Properties, eg one from dodgy versions of Jasper Reports + * See https://github.com/nestoru/xlsxenc/ and + * http://stackoverflow.com/questions/28593223 + */ + @Test + public void encryptPackageWithoutCoreProperties() throws Exception { + // Open our file without core properties + File inp = POIDataSamples.getOpenXML4JInstance().getFile("OPCCompliance_NoCoreProperties.xlsx"); + OPCPackage pkg = OPCPackage.open(inp.getPath()); + + // It doesn't have any core properties yet + assertEquals(0, pkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(pkg.getPackageProperties()); + assertNotNull(pkg.getPackageProperties().getLanguageProperty()); + assertNull(pkg.getPackageProperties().getLanguageProperty().getValue()); + + // Encrypt it + EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile); + NPOIFSFileSystem fs = new NPOIFSFileSystem(); + + Encryptor enc = info.getEncryptor(); + enc.confirmPassword("password"); + OutputStream os = enc.getDataStream(fs); + pkg.save(os); + pkg.revert(); + + // Save the resulting OLE2 document, and re-open it + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + fs.writeFilesystem(baos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + NPOIFSFileSystem inpFS = new NPOIFSFileSystem(bais); + + // Check we can decrypt it + info = new EncryptionInfo(inpFS); + Decryptor d = Decryptor.getInstance(info); + assertEquals(true, d.verifyPassword("password")); + + OPCPackage inpPkg = OPCPackage.open(d.getDataStream(inpFS)); + + // Check it now has empty core properties + assertEquals(1, inpPkg.getPartsByContentType(ContentTypes.CORE_PROPERTIES_PART).size()); + assertNotNull(inpPkg.getPackageProperties()); + assertNotNull(inpPkg.getPackageProperties().getLanguageProperty()); + assertNull(inpPkg.getPackageProperties().getLanguageProperty().getValue()); + } + @Test @Ignore public void inPlaceRewrite() throws Exception { diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java index ded14dfba..d0eeb3d47 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java @@ -316,7 +316,7 @@ public class TestSignatureInfo { signatureConfig.addSignatureFacet(new XAdESXLSignatureFacet()); // check for internet, no error means it works - boolean mockTsp = (getAccessError("http://timestamp.comodoca.com/rfc3161", true, 10000) == null); + boolean mockTsp = (getAccessError("http://timestamp.comodoca.com/rfc3161", true, 10000) != null); // http://timestamping.edelweb.fr/service/tsp // http://tsa.belgium.be/connect @@ -382,11 +382,13 @@ public class TestSignatureInfo { si.confirmSignature(); } catch (RuntimeException e) { // only allow a ConnectException because of timeout, we see this in Jenkins from time to time... - assertNotNull("Only allowing ConnectException here, but had: " + e, e.getCause()); + if(e.getCause() == null) { + throw e; + } if(!(e.getCause() instanceof ConnectException)) { throw e; } - assertTrue("Only allowing ConnectException here, but had: " + e, e.getCause().getMessage().contains("timed out")); + assertTrue("Only allowing ConnectException with 'timed out' as message here, but had: " + e, e.getCause().getMessage().contains("timed out")); } // verify diff --git a/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java b/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java index 28983ff6f..f3fcbb889 100644 --- a/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java +++ b/src/ooxml/testcases/org/apache/poi/ss/TestWorkbookFactory.java @@ -17,101 +17,282 @@ package org.apache.poi.ss; +import java.io.ByteArrayInputStream; +import java.io.File; import java.io.InputStream; +import org.apache.poi.EmptyFileException; +import org.apache.poi.EncryptedDocumentException; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.util.TempFile; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.openxml4j.opc.OPCPackage; import junit.framework.TestCase; public final class TestWorkbookFactory extends TestCase { - private String xls; - private String xlsx; - private String txt; + private String xls; + private String xlsx; + private String[] xls_prot; + private String[] xlsx_prot; + private String txt; - protected void setUp() { - xls = "SampleSS.xls"; - xlsx = "SampleSS.xlsx"; - txt = "SampleSS.txt"; - } + protected void setUp() { + xls = "SampleSS.xls"; + xlsx = "SampleSS.xlsx"; + xls_prot = new String[] {"password.xls", "password"}; + xlsx_prot = new String[]{"protected_passtika.xlsx", "tika"}; + txt = "SampleSS.txt"; + } - public void testCreateNative() throws Exception { - Workbook wb; + public void testCreateNative() throws Exception { + Workbook wb; - // POIFS -> hssf - wb = WorkbookFactory.create( - new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls)) - ); - assertNotNull(wb); - assertTrue(wb instanceof HSSFWorkbook); - wb.close(); + // POIFS -> hssf + wb = WorkbookFactory.create( + new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream(xls)) + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); - // Package -> xssf - wb = WorkbookFactory.create( - OPCPackage.open( + // Package -> xssf + wb = WorkbookFactory.create( + OPCPackage.open( HSSFTestDataSamples.openSampleFileStream(xlsx)) - ); - assertNotNull(wb); - assertTrue(wb instanceof XSSFWorkbook); - // TODO: this re-writes the sample-file?! wb.close(); - } + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + // TODO: this re-writes the sample-file?! wb.close(); + } - /** - * Creates the appropriate kind of Workbook, but - * checking the mime magic at the start of the - * InputStream, then creating what's required. - */ - public void testCreateGeneric() throws Exception { - Workbook wb; + public void testCreateReadOnly() throws Exception { + Workbook wb; - // InputStream -> either - wb = WorkbookFactory.create( - HSSFTestDataSamples.openSampleFileStream(xls) - ); - assertNotNull(wb); - assertTrue(wb instanceof HSSFWorkbook); - wb.close(); + // POIFS -> hssf + wb = WorkbookFactory.create(HSSFTestDataSamples.getSampleFile(xls), null, true); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); - wb = WorkbookFactory.create( - HSSFTestDataSamples.openSampleFileStream(xlsx) - ); - assertNotNull(wb); - assertTrue(wb instanceof XSSFWorkbook); - // TODO: this re-writes the sample-file?! wb.close(); - - // File -> either - wb = WorkbookFactory.create( - HSSFTestDataSamples.getSampleFile(xls) - ); - assertNotNull(wb); - assertTrue(wb instanceof HSSFWorkbook); - wb.close(); + // Package -> xssf + wb = WorkbookFactory.create(HSSFTestDataSamples.getSampleFile(xlsx), null, true); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + wb.close(); + } - wb = WorkbookFactory.create( - HSSFTestDataSamples.getSampleFile(xlsx) - ); - assertNotNull(wb); - assertTrue(wb instanceof XSSFWorkbook); - - // TODO: close() re-writes the sample-file?! Resort to revert() for now to close file handle... - ((XSSFWorkbook)wb).getPackage().revert(); + /** + * Creates the appropriate kind of Workbook, but + * checking the mime magic at the start of the + * InputStream, then creating what's required. + */ + public void testCreateGeneric() throws Exception { + Workbook wb; - // Invalid type -> exception - try { - InputStream stream = HSSFTestDataSamples.openSampleFileStream(txt); - try { + // InputStream -> either + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xls) + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); + + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xlsx) + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + // TODO: this re-writes the sample-file?! wb.close(); + + // File -> either + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xls) + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); + + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xlsx) + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + + // TODO: close() re-writes the sample-file?! Resort to revert() for now to close file handle... + ((XSSFWorkbook)wb).getPackage().revert(); + + // Invalid type -> exception + try { + InputStream stream = HSSFTestDataSamples.openSampleFileStream(txt); + try { wb = WorkbookFactory.create(stream); - } finally { - stream.close(); - } - fail(); - } catch(IllegalArgumentException e) { - // Good - } - } + } finally { + stream.close(); + } + fail(); + } catch(IllegalArgumentException e) { + // Good + } + } + + /** + * Check that the overloaded stream methods which take passwords work properly + */ + public void testCreateWithPasswordFromStream() throws Exception { + Workbook wb; + + + // Unprotected, no password given, opens normally + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xls), null + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); + + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xlsx), null + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + + + // Unprotected, wrong password, opens normally + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xls), "wrong" + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); + + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xlsx), "wrong" + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + + + // Protected, correct password, opens fine + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xls_prot[0]), xls_prot[1] + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); + + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xlsx_prot[0]), xlsx_prot[1] + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + + + // Protected, wrong password, throws Exception + try { + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xls_prot[0]), "wrong" + ); + fail("Shouldn't be able to open with the wrong password"); + } catch (EncryptedDocumentException e) {} + + try { + wb = WorkbookFactory.create( + HSSFTestDataSamples.openSampleFileStream(xlsx_prot[0]), "wrong" + ); + fail("Shouldn't be able to open with the wrong password"); + } catch (EncryptedDocumentException e) {} + } + + /** + * Check that the overloaded file methods which take passwords work properly + */ + public void testCreateWithPasswordFromFile() throws Exception { + Workbook wb; + + // Unprotected, no password given, opens normally + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xls), null + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); + + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xlsx), null + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + + + // Unprotected, wrong password, opens normally + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xls), "wrong" + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); + + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xlsx), "wrong" + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + + + // Protected, correct password, opens fine + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xls_prot[0]), xls_prot[1] + ); + assertNotNull(wb); + assertTrue(wb instanceof HSSFWorkbook); + wb.close(); + + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xlsx_prot[0]), xlsx_prot[1] + ); + assertNotNull(wb); + assertTrue(wb instanceof XSSFWorkbook); + + + // Protected, wrong password, throws Exception + try { + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xls_prot[0]), "wrong" + ); + fail("Shouldn't be able to open with the wrong password"); + } catch (EncryptedDocumentException e) {} + + try { + wb = WorkbookFactory.create( + HSSFTestDataSamples.getSampleFile(xlsx_prot[0]), "wrong" + ); + fail("Shouldn't be able to open with the wrong password"); + } catch (EncryptedDocumentException e) {} + } + + /** + * Check that a helpful exception is given on an empty file / stream + */ + public void testEmptyFile() throws Exception { + InputStream emptyStream = new ByteArrayInputStream(new byte[0]); + File emptyFile = TempFile.createTempFile("empty", ".poi"); + + try { + WorkbookFactory.create(emptyStream); + fail("Shouldn't be able to create for an empty stream"); + } catch (EmptyFileException e) { + } + + try { + WorkbookFactory.create(emptyFile); + fail("Shouldn't be able to create for an empty file"); + } catch (EmptyFileException e) { + } + emptyFile.delete(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/ss/formula/TestFormulaParser.java b/src/ooxml/testcases/org/apache/poi/ss/formula/TestFormulaParser.java new file mode 100644 index 000000000..f90c653a9 --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/ss/formula/TestFormulaParser.java @@ -0,0 +1,66 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.apache.poi.ss.formula; + +import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import junit.framework.TestCase; + +/** + * Test {@link FormulaParser}'s handling of row numbers at the edge of the + * HSSF/XSSF ranges. + * + * @author David North + */ +public class TestFormulaParser extends TestCase { + + public void testHSSFFailsForOver65536() { + FormulaParsingWorkbook workbook = HSSFEvaluationWorkbook.create(new HSSFWorkbook()); + try { + FormulaParser.parse("Sheet1!1:65537", workbook, FormulaType.CELL, 0); + fail("Expected exception"); + } + catch (FormulaParseException expected) { + } + } + + public void testHSSFPassCase() { + FormulaParsingWorkbook workbook = HSSFEvaluationWorkbook.create(new HSSFWorkbook()); + FormulaParser.parse("Sheet1!1:65536", workbook, FormulaType.CELL, 0); + } + + public void testXSSFWorksForOver65536() { + FormulaParsingWorkbook workbook = XSSFEvaluationWorkbook.create(new XSSFWorkbook()); + FormulaParser.parse("Sheet1!1:65537", workbook, FormulaType.CELL, 0); + } + + public void testXSSFFailCase() { + FormulaParsingWorkbook workbook = XSSFEvaluationWorkbook.create(new XSSFWorkbook()); + try { + FormulaParser.parse("Sheet1!1:1048577", workbook, FormulaType.CELL, 0); // one more than max rows. + fail("Expected exception"); + } + catch (FormulaParseException expected) { + } + } + +} diff --git a/src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java b/src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java index ba55f070a..f78819ca3 100644 --- a/src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java +++ b/src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java @@ -19,6 +19,7 @@ package org.apache.poi.ss.usermodel; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.xssf.SXSSFITestDataProvider; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.streaming.SXSSFCell; @@ -48,32 +49,5 @@ public abstract class BaseTestXCell extends BaseTestCell { // invalid characters are replaced with question marks assertEquals("???<>\t\n\u00a0 &\"POI\'\u2122", wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue()); - - } - - public void testEncodingbeloAscii(){ - Workbook xwb = XSSFITestDataProvider.instance.createWorkbook(); - Cell xCell = xwb.createSheet().createRow(0).createCell(0); - - Workbook swb = SXSSFITestDataProvider.instance.createWorkbook(); - Cell sCell = swb.createSheet().createRow(0).createCell(0); - - StringBuffer sb = new StringBuffer(); - // test all possible characters - for(int i = 0; i < Character.MAX_VALUE; i++) sb.append((char)i) ; - - String str = sb.toString(); - - xCell.setCellValue(str); - assertEquals(str, xCell.getStringCellValue()); - sCell.setCellValue(str); - assertEquals(str, sCell.getStringCellValue()); - - xwb = XSSFITestDataProvider.instance.writeOutAndReadBack(xwb); - swb = SXSSFITestDataProvider.instance.writeOutAndReadBack(swb); - xCell = xwb.getSheetAt(0).createRow(0).createCell(0); - sCell = swb.getSheetAt(0).createRow(0).createCell(0); - - assertEquals(xCell.getStringCellValue(), sCell.getStringCellValue()); } } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java index 6d66caefe..35f30a36d 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/TestXSLFBugs.java @@ -18,6 +18,7 @@ package org.apache.poi.xslf; import static junit.framework.TestCase.assertEquals; import static org.apache.poi.POITestCase.assertContains; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; @@ -47,7 +48,6 @@ import org.apache.poi.xslf.usermodel.XSLFSlide; import org.apache.poi.xslf.usermodel.XSLFSlideLayout; import org.junit.Ignore; import org.junit.Test; - public class TestXSLFBugs { @Test @@ -196,7 +196,7 @@ public class TestXSLFBugs { } @Test - // @Ignore("Similar to TestFontRendering it doesn't make sense to compare images because of tiny rendering differences in windows/unix") + @Ignore("Similar to TestFontRendering it doesn't make sense to compare images because of tiny rendering differences in windows/unix") public void bug54542() throws Exception { XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("54542_cropped_bitmap.pptx"); @@ -259,6 +259,107 @@ public class TestXSLFBugs { ss.setSlideOrder(slide, 2); validateSlides(ss, true, "Slide1","Slide2","New slide"); } + + /** + * When working with >9 images, make sure the sorting ensures + * that image10.foo isn't between image1.foo and image2.foo + */ + @Test + public void test57552() throws Exception { + XMLSlideShow ss = new XMLSlideShow(); + for (String s : new String[]{"Slide1","Slide2"}) { + ss.createSlide().createTextBox().setText(s); + } + + // Slide starts with just layout relation + XSLFSlide slide = ss.getSlides().get(0); + assertEquals(0, ss.getAllPictures().size()); + assertEquals(1, slide.getShapes().size()); + + assertEquals(1, slide.getRelations().size()); + assertRelationEquals(XSLFRelation.SLIDE_LAYOUT, slide.getRelations().get(0)); + + // Some dummy pictures + byte[][] pics = new byte[15][3]; + for (int i=0; i 0; sn--) - { - wb.removeSheetAt(sn); - } - } - // When this is fixed, the test case should go to BaseTestXCell with // adjustments to use _testDataProvider to also verify this for XSSF public void testBug57294() throws IOException { @@ -244,65 +218,159 @@ public final class TestUnfixedBugs extends TestCase { assertEquals(4, strBack.getIndexOfFormattingRun(2)); } - @Test - public void testBug56655() { - XSSFWorkbook wb = new XSSFWorkbook(); - Sheet sheet = wb.createSheet(); - - setCellFormula(sheet, 0, 0, "#VALUE!"); - setCellFormula(sheet, 0, 1, "SUMIFS(A:A,A:A,#VALUE!)"); + @Test + public void testBug55752() throws IOException { + Workbook wb = new XSSFWorkbook(); + try { + Sheet sheet = wb.createSheet("test"); + + for (int i = 0; i < 4; i++) { + Row row = sheet.createRow(i); + for (int j = 0; j < 2; j++) { + Cell cell = row.createCell(j); + cell.setCellStyle(wb.createCellStyle()); + } + } + + // set content + Row row1 = sheet.getRow(0); + row1.getCell(0).setCellValue("AAA"); + Row row2 = sheet.getRow(1); + row2.getCell(0).setCellValue("BBB"); + Row row3 = sheet.getRow(2); + row3.getCell(0).setCellValue("CCC"); + Row row4 = sheet.getRow(3); + row4.getCell(0).setCellValue("DDD"); + + // merge cells + CellRangeAddress range1 = new CellRangeAddress(0, 0, 0, 1); + sheet.addMergedRegion(range1); + CellRangeAddress range2 = new CellRangeAddress(1, 1, 0, 1); + sheet.addMergedRegion(range2); + CellRangeAddress range3 = new CellRangeAddress(2, 2, 0, 1); + sheet.addMergedRegion(range3); + assertEquals(0, range3.getFirstColumn()); + assertEquals(1, range3.getLastColumn()); + assertEquals(2, range3.getLastRow()); + CellRangeAddress range4 = new CellRangeAddress(3, 3, 0, 1); + sheet.addMergedRegion(range4); + + // set border + RegionUtil.setBorderBottom(CellStyle.BORDER_THIN, range1, sheet, wb); + + row2.getCell(0).getCellStyle().setBorderBottom(CellStyle.BORDER_THIN); + row2.getCell(1).getCellStyle().setBorderBottom(CellStyle.BORDER_THIN); - XSSFFormulaEvaluator.evaluateAllFormulaCells(wb); + Cell cell0 = CellUtil.getCell(row3, 0); + CellUtil.setCellStyleProperty(cell0, wb, CellUtil.BORDER_BOTTOM, CellStyle.BORDER_THIN); + Cell cell1 = CellUtil.getCell(row3, 1); + CellUtil.setCellStyleProperty(cell1, wb, CellUtil.BORDER_BOTTOM, CellStyle.BORDER_THIN); - assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 0,0).getCachedFormulaResultType()); - assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0,0).getErrorCellValue()); - assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 0,1).getCachedFormulaResultType()); - assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0,1).getErrorCellValue()); - } - - @Test - public void testBug56655a() { - XSSFWorkbook wb = new XSSFWorkbook(); - Sheet sheet = wb.createSheet(); - - setCellFormula(sheet, 0, 0, "B1*C1"); - sheet.getRow(0).createCell(1).setCellValue("A"); - setCellFormula(sheet, 1, 0, "B1*C1"); - sheet.getRow(1).createCell(1).setCellValue("A"); - setCellFormula(sheet, 0, 3, "SUMIFS(A:A,A:A,A2)"); - - XSSFFormulaEvaluator.evaluateAllFormulaCells(wb); - - assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 0, 0).getCachedFormulaResultType()); - assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0, 0).getErrorCellValue()); - assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 1, 0).getCachedFormulaResultType()); - assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 1, 0).getErrorCellValue()); - assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 0, 3).getCachedFormulaResultType()); - assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0, 3).getErrorCellValue()); - } - - /** - * @param row 0-based - * @param column 0-based - */ - void setCellFormula(Sheet sheet, int row, int column, String formula) { - Row r = sheet.getRow(row); - if (r == null) { - r = sheet.createRow(row); + RegionUtil.setBorderBottom(CellStyle.BORDER_THIN, range4, sheet, wb); + + // write to file + OutputStream stream = new FileOutputStream(new File("C:/temp/55752.xlsx")); + try { + wb.write(stream); + } finally { + stream.close(); + } + } finally { + wb.close(); } - Cell cell = r.getCell(column); - if (cell == null) { - cell = r.createCell(column); - } - cell.setCellType(XSSFCell.CELL_TYPE_FORMULA); - cell.setCellFormula(formula); } - /** - * @param rowNo 0-based - * @param column 0-based - */ - Cell getCell(Sheet sheet, int rowNo, int column) { - return sheet.getRow(rowNo).getCell(column); + @Test + public void test57423() throws IOException { + Workbook wb = XSSFTestDataSamples.openSampleWorkbook("57423.xlsx"); + + Sheet testSheet = wb.getSheetAt(0); + + // row shift (negative or positive) causes corrupted output xlsx file when the shift value is bigger + // than the number of rows being shifted + // Excel 2010 on opening the output file says: + // "Excel found unreadable content" and offers recovering the file by removing the unreadable content + // This can be observed in cases like the following: + // negative shift of 1 row by less than -1 + // negative shift of 2 rows by less than -2 + // positive shift of 1 row by 2 or more + // positive shift of 2 rows by 3 or more + + //testSheet.shiftRows(4, 5, -3); + testSheet.shiftRows(10, 10, 2); + + checkRows57423(testSheet); + + Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); + + /*FileOutputStream stream = new FileOutputStream("C:\\temp\\57423.xlsx"); + try { + wb.write(stream); + } finally { + stream.close(); + }*/ + + wb.close(); + + checkRows57423(wbBack.getSheetAt(0)); + + wbBack.close(); + } + + private void checkRows57423(Sheet testSheet) throws IOException { + checkRow57423(testSheet, 0, "0"); + checkRow57423(testSheet, 1, "1"); + checkRow57423(testSheet, 2, "2"); + checkRow57423(testSheet, 3, "3"); + checkRow57423(testSheet, 4, "4"); + checkRow57423(testSheet, 5, "5"); + checkRow57423(testSheet, 6, "6"); + checkRow57423(testSheet, 7, "7"); + checkRow57423(testSheet, 8, "8"); + checkRow57423(testSheet, 9, "9"); + + assertNull("Row number 10 should be gone after the shift", + testSheet.getRow(10)); + + checkRow57423(testSheet, 11, "11"); + checkRow57423(testSheet, 12, "10"); + checkRow57423(testSheet, 13, "13"); + checkRow57423(testSheet, 14, "14"); + checkRow57423(testSheet, 15, "15"); + checkRow57423(testSheet, 16, "16"); + checkRow57423(testSheet, 17, "17"); + checkRow57423(testSheet, 18, "18"); + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + ((XSSFSheet)testSheet).write(stream); + } finally { + stream.close(); + } + + // verify that the resulting XML has the rows in correct order as required by Excel + String xml = new String(stream.toByteArray()); + int posR12 = xml.indexOf(" 0; sn--) + { + wb.removeSheetAt(sn); + } + } + + /** + * Sums 2 plus the cell at the left, indirectly to avoid reference + * problems when deleting columns, conditionally to stop recursion + */ + private static final String FORMULA1 = + "IF( INDIRECT( ADDRESS( ROW(), COLUMN()-1 ) ) = 0, 0," + + "INDIRECT( ADDRESS( ROW(), COLUMN()-1 ) ) ) + 2"; + + /** + * Sums 2 plus the upper cell, indirectly to avoid reference + * problems when deleting rows, conditionally to stop recursion + */ + private static final String FORMULA2 = + "IF( INDIRECT( ADDRESS( ROW()-1, COLUMN() ) ) = 0, 0," + + "INDIRECT( ADDRESS( ROW()-1, COLUMN() ) ) ) + 2"; + + /** + * Expected: + + * [ 0][ 2][ 4] + * @throws IOException + */ + @Test + public void testBug56820_Formula1() throws IOException { + Workbook wb = new XSSFWorkbook(); + try { + FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); + Sheet sh = wb.createSheet(); + + sh.createRow(0).createCell(0).setCellValue(0.0d); + Cell formulaCell1 = sh.getRow(0).createCell(1); + Cell formulaCell2 = sh.getRow(0).createCell(2); + formulaCell1.setCellFormula(FORMULA1); + formulaCell2.setCellFormula(FORMULA1); + + double A1 = evaluator.evaluate(formulaCell1).getNumberValue(); + double A2 = evaluator.evaluate(formulaCell2).getNumberValue(); + + assertEquals(2, A1, 0); + assertEquals(4, A2, 0); //<-- FAILS EXPECTATIONS + } finally { + wb.close(); + } + } + + /** + * Expected: + + * [ 0] <- number + * [ 2] <- formula + * [ 4] <- formula + * @throws IOException + */ + @Test + public void testBug56820_Formula2() throws IOException { + Workbook wb = new XSSFWorkbook(); + try { + FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); + Sheet sh = wb.createSheet(); + + sh.createRow(0).createCell(0).setCellValue(0.0d); + Cell formulaCell1 = sh.createRow(1).createCell(0); + Cell formulaCell2 = sh.createRow(2).createCell(0); + formulaCell1.setCellFormula(FORMULA2); + formulaCell2.setCellFormula(FORMULA2); + + double A1 = evaluator.evaluate(formulaCell1).getNumberValue(); + double A2 = evaluator.evaluate(formulaCell2).getNumberValue(); //<-- FAILS EVALUATION + + assertEquals(2, A1, 0); + assertEquals(4, A2, 0); + } finally { + wb.close(); + } + } + + @Test + public void test56467() throws IOException { + Workbook wb = XSSFTestDataSamples.openSampleWorkbook("picture.xlsx"); + try { + Sheet orig = wb.getSheetAt(0); + assertNotNull(orig); + + Sheet sheet = wb.cloneSheet(0); + Drawing drawing = sheet.createDrawingPatriarch(); + for (XSSFShape shape : ((XSSFDrawing) drawing).getShapes()) { + if (shape instanceof XSSFPicture) { + XSSFPictureData pictureData = ((XSSFPicture) shape).getPictureData(); + assertNotNull(pictureData); + } + } + +// OutputStream out = new FileOutputStream("/tmp/56467.xls"); +// try { +// wb.write(out); +// } finally { +// out.close(); +// } + } finally { + wb.close(); + } + } + + /** + * OOXML-Strict files + * Not currently working - namespace mis-match from XMLBeans + */ + @Test + @Ignore("XMLBeans namespace mis-match on ooxml-strict files") + public void test57699() throws Exception { + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("sample.strict.xlsx"); + assertEquals(3, wb.getNumberOfSheets()); + // TODO Check sheet contents + // TODO Check formula evaluation + + XSSFWorkbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); + assertEquals(3, wbBack.getNumberOfSheets()); + // TODO Re-check sheet contents + // TODO Re-check formula evaluation + } + + @Test + public void testBug56295_MergeXlslsWithStyles() throws IOException { + XSSFWorkbook xlsToAppendWorkbook = XSSFTestDataSamples.openSampleWorkbook("56295.xlsx"); + XSSFSheet sheet = xlsToAppendWorkbook.getSheetAt(0); + XSSFRow srcRow = sheet.getRow(0); + XSSFCell oldCell = srcRow.getCell(0); + XSSFCellStyle cellStyle = oldCell.getCellStyle(); + + checkStyle(cellStyle); + +// StylesTable table = xlsToAppendWorkbook.getStylesSource(); +// List fills = table.getFills(); +// System.out.println("Having " + fills.size() + " fills"); +// for(XSSFCellFill fill : fills) { +// System.out.println("Fill: " + fill.getFillBackgroundColor() + "/" + fill.getFillForegroundColor()); +// } + + XSSFWorkbook targetWorkbook = new XSSFWorkbook(); + XSSFSheet newSheet = targetWorkbook.createSheet(sheet.getSheetName()); + XSSFRow destRow = newSheet.createRow(0); + XSSFCell newCell = destRow.createCell(0); + + //newCell.getCellStyle().cloneStyleFrom(cellStyle); + CellStyle newCellStyle = targetWorkbook.createCellStyle(); + newCellStyle.cloneStyleFrom(cellStyle); + newCell.setCellStyle(newCellStyle); + checkStyle(newCell.getCellStyle()); + newCell.setCellValue(oldCell.getStringCellValue()); + +// OutputStream os = new FileOutputStream("output.xlsm"); +// try { +// targetWorkbook.write(os); +// } finally { +// os.close(); +// } + + XSSFWorkbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(targetWorkbook); + XSSFCellStyle styleBack = wbBack.getSheetAt(0).getRow(0).getCell(0).getCellStyle(); + checkStyle(styleBack); + } + + /** + * Paragraph with property BuFont but none of the properties + * BuNone, BuChar, and BuAutoNum, used to trigger a NPE + * Excel treats this as not-bulleted, so now do we + */ + @Test + public void testBug57826() { + XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("57826.xlsx"); + + assertTrue("no sheets in workbook", workbook.getNumberOfSheets() >= 1); + XSSFSheet sheet = workbook.getSheetAt(0); + + XSSFDrawing drawing = sheet.getDrawingPatriarch(); + assertNotNull(drawing); + + List shapes = drawing.getShapes(); + assertEquals(1, shapes.size()); + assertTrue(shapes.get(0) instanceof XSSFSimpleShape); + + XSSFSimpleShape shape = (XSSFSimpleShape)shapes.get(0); + + // Used to throw a NPE + String text = shape.getText(); + + // No bulleting info included + assertEquals("test ok", text); + } + + private void checkStyle(XSSFCellStyle cellStyle) { + assertNotNull(cellStyle); + assertEquals(0, cellStyle.getFillForegroundColor()); + assertNotNull(cellStyle.getFillForegroundXSSFColor()); + XSSFColor fgColor = cellStyle.getFillForegroundColorColor(); + assertNotNull(fgColor); + assertEquals("FF00FFFF", fgColor.getARGBHex()); + + assertEquals(0, cellStyle.getFillBackgroundColor()); + assertNotNull(cellStyle.getFillBackgroundXSSFColor()); + XSSFColor bgColor = cellStyle.getFillBackgroundColorColor(); + assertNotNull(bgColor); + assertEquals("FF00FFFF", fgColor.getARGBHex()); + } + + @Test + public void bug57642() throws Exception { + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet s = wb.createSheet("TestSheet"); + XSSFCell c = s.createRow(0).createCell(0); + c.setCellFormula("ISERROR(TestSheet!A1)"); + c = s.createRow(1).createCell(1); + c.setCellFormula("ISERROR(B2)"); + + wb.setSheetName(0, "CSN"); + c = s.getRow(0).getCell(0); + assertEquals("ISERROR(CSN!A1)", c.getCellFormula()); + c = s.getRow(1).getCell(1); + assertEquals("ISERROR(B2)", c.getCellFormula()); + + wb.close(); + } + + /** + * .xlsx supports 64000 cell styles, the style indexes after + * 32,767 must not be -32,768, then -32,767, -32,766 + */ + @Test + public void bug57880() throws Exception { + int numStyles = 33000; + XSSFWorkbook wb = new XSSFWorkbook(); + XSSFSheet s = wb.createSheet("TestSheet"); + XSSFDataFormat fmt = wb.getCreationHelper().createDataFormat(); + for (int i=1; i data; + data = new TreeMap(); + data.put("1", new Object[] {"ID", "NAME", "LASTNAME"}); + data.put("2", new Object[] {2, "Amit", "Shukla"}); + data.put("3", new Object[] {1, "Lokesh", "Gupta"}); + data.put("4", new Object[] {4, "John", "Adwards"}); + data.put("5", new Object[] {2, "Brian", "Schultz"}); + + Set keyset = data.keySet(); + int rownum = 1; + for (String key : keyset) + { + final Row row; + if(createRow) { + row = sheet.createRow(rownum++); + } else { + row = sheet.getRow(rownum++); + } + assertNotNull(row); + + Object [] objArr = data.get(key); + int cellnum = 0; + for (Object obj : objArr) + { + Cell cell = row.getCell(cellnum); + if(cell == null){ + cell = row.createCell(cellnum); + } else { + if(cell.getCellType() == Cell.CELL_TYPE_FORMULA) { + cell.setCellFormula(null); + cell.getCellStyle().setDataFormat((short) 0); + } + } + if(obj instanceof String) { + cell.setCellValue((String)obj); + } else if(obj instanceof Integer) { + cell.setCellValue((Integer)obj); + } + cellnum++; + } + } + + XSSFFormulaEvaluator.evaluateAllFormulaCells((XSSFWorkbook) wb); + wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); + + CalculationChain chain = ((XSSFWorkbook)wb).getCalculationChain(); + CTCalcCell[] cArray = chain.getCTCalcChain().getCArray(); + for(CTCalcCell calc : cArray) { + // A2 to A6 should be gone + assertFalse(calc.getR().equals("A2")); + assertFalse(calc.getR().equals("A3")); + assertFalse(calc.getR().equals("A4")); + assertFalse(calc.getR().equals("A5")); + assertFalse(calc.getR().equals("A6")); + } + + /*FileOutputStream out = new FileOutputStream(new File("C:\\temp\\56574.xlsx")); + try { + wb.write(out); + } finally { + out.close(); + }*/ + + Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); + Sheet sheetBack = wbBack.getSheet("Func"); + assertNotNull(sheetBack); + + chain = ((XSSFWorkbook)wbBack).getCalculationChain(); + cArray = chain.getCTCalcChain().getCArray(); + for(CTCalcCell calc : cArray) { + // A2 to A6 should be gone + assertFalse(calc.getR().equals("A2")); + assertFalse(calc.getR().equals("A3")); + assertFalse(calc.getR().equals("A4")); + assertFalse(calc.getR().equals("A5")); + assertFalse(calc.getR().equals("A6")); + } + + wb.close(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java index 9740e416d..1d020e9a3 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java @@ -19,6 +19,8 @@ package org.apache.poi.xssf.usermodel; import java.io.IOException; +import org.apache.poi.hssf.HSSFITestDataProvider; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.BaseTestXCell; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DataFormatter; @@ -28,6 +30,7 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.SXSSFITestDataProvider; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.model.SharedStringsTable; @@ -402,4 +405,48 @@ public final class TestXSSFCell extends BaseTestXCell { wb.close(); } } + + public void testEncodingbeloAscii(){ + StringBuffer sb = new StringBuffer(); + // test all possible characters + for(int i = 0; i < Character.MAX_VALUE; i++) { + sb.append((char)i); + } + + String strAll = sb.toString(); + + // process in chunks as we have a limit on size of column now + int pos = 0; + while(pos < strAll.length()) { + String str = strAll.substring(pos, Math.min(strAll.length(), pos+SpreadsheetVersion.EXCEL2007.getMaxTextLength())); + + Workbook wb = HSSFITestDataProvider.instance.createWorkbook(); + Cell cell = wb.createSheet().createRow(0).createCell(0); + + Workbook xwb = XSSFITestDataProvider.instance.createWorkbook(); + Cell xCell = xwb.createSheet().createRow(0).createCell(0); + + Workbook swb = SXSSFITestDataProvider.instance.createWorkbook(); + Cell sCell = swb.createSheet().createRow(0).createCell(0); + + cell.setCellValue(str); + assertEquals(str, cell.getStringCellValue()); + xCell.setCellValue(str); + assertEquals(str, xCell.getStringCellValue()); + sCell.setCellValue(str); + assertEquals(str, sCell.getStringCellValue()); + + Workbook wbBack = HSSFITestDataProvider.instance.writeOutAndReadBack(wb); + Workbook xwbBack = XSSFITestDataProvider.instance.writeOutAndReadBack(xwb); + Workbook swbBack = SXSSFITestDataProvider.instance.writeOutAndReadBack(swb); + cell = wbBack.getSheetAt(0).createRow(0).createCell(0); + xCell = xwbBack.getSheetAt(0).createRow(0).createCell(0); + sCell = swbBack.getSheetAt(0).createRow(0).createCell(0); + + assertEquals(cell.getStringCellValue(), xCell.getStringCellValue()); + assertEquals(cell.getStringCellValue(), sCell.getStringCellValue()); + + pos += SpreadsheetVersion.EXCEL97.getMaxTextLength(); + } + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCellStyle.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCellStyle.java index 8d427be55..6c7893ed5 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCellStyle.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCellStyle.java @@ -17,20 +17,26 @@ package org.apache.poi.xssf.usermodel; +import java.io.IOException; + import junit.framework.TestCase; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.DataFormat; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder; import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill; +import org.junit.Test; import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; public class TestXSSFCellStyle extends TestCase { @@ -82,6 +88,9 @@ public class TestXSSFCellStyle extends TestCase { stylesTable.putCellStyleXf(cellStyleXf); stylesTable.putCellXf(cellXf); cellStyle = new XSSFCellStyle(1, 1, stylesTable, null); + + assertNotNull(stylesTable.getFillAt(1).getCTFill().getPatternFill()); + assertEquals(STPatternType.INT_DARK_GRAY, stylesTable.getFillAt(1).getCTFill().getPatternFill().getPatternType().intValue()); } public void testGetSetBorderBottom() { @@ -551,7 +560,7 @@ public class TestXSSFCellStyle extends TestCase { assertEquals(IndexedColors.AUTOMATIC.getIndex(), cellStyle.getFillBackgroundColor()); } - public void testDefaultStyles() { + public void testDefaultStyles() throws IOException { XSSFWorkbook wb1 = new XSSFWorkbook(); @@ -577,6 +586,7 @@ public class TestXSSFCellStyle extends TestCase { assertEquals(style2.getBorderLeft(), style1.getBorderLeft()); assertEquals(style2.getBorderRight(), style1.getBorderRight()); assertEquals(style2.getBorderTop(), style1.getBorderTop()); + wb2.close(); } @@ -618,7 +628,7 @@ public class TestXSSFCellStyle extends TestCase { public void testGetFillPattern() { - assertEquals(CellStyle.NO_FILL, cellStyle.getFillPattern()); + assertEquals(STPatternType.INT_DARK_GRAY-1, cellStyle.getFillPattern()); int num = stylesTable.getFills().size(); cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); @@ -885,4 +895,50 @@ public class TestXSSFCellStyle extends TestCase { assertNotNull(XSSFTestDataSamples.writeOutAndReadBack(wb)); assertNotNull(XSSFTestDataSamples.writeOutAndReadBack(wbOrig)); } + + @Test + public void testSetColor() throws IOException { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet(); + Row row = sheet.createRow(0); + + //CreationHelper ch = wb.getCreationHelper(); + DataFormat format = wb.createDataFormat(); + Cell cell = row.createCell(1); + cell.setCellValue("somevalue"); + CellStyle cellStyle = wb.createCellStyle(); + + + cellStyle.setDataFormat(format.getFormat("###0")); + + cellStyle.setFillBackgroundColor(IndexedColors.DARK_BLUE.getIndex()); + cellStyle.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex()); + cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); + + cellStyle.setAlignment(CellStyle.ALIGN_RIGHT); + cellStyle.setVerticalAlignment(CellStyle.VERTICAL_TOP); + + cell.setCellStyle(cellStyle); + + /*OutputStream stream = new FileOutputStream("C:\\temp\\CellColor.xlsx"); + try { + wb.write(stream); + } finally { + stream.close(); + }*/ + + Workbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); + Cell cellBack = wbBack.getSheetAt(0).getRow(0).getCell(1); + assertNotNull(cellBack); + CellStyle styleBack = cellBack.getCellStyle(); + assertEquals(IndexedColors.DARK_BLUE.getIndex(), styleBack.getFillBackgroundColor()); + assertEquals(IndexedColors.DARK_BLUE.getIndex(), styleBack.getFillForegroundColor()); + assertEquals(CellStyle.ALIGN_RIGHT, styleBack.getAlignment()); + assertEquals(CellStyle.VERTICAL_TOP, styleBack.getVerticalAlignment()); + assertEquals(CellStyle.SOLID_FOREGROUND, styleBack.getFillPattern()); + + wbBack.close(); + + wb.close(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFConditionalFormatting.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFConditionalFormatting.java index 325c5342d..81220355d 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFConditionalFormatting.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFConditionalFormatting.java @@ -19,17 +19,32 @@ package org.apache.poi.xssf.usermodel; import org.apache.poi.ss.usermodel.BaseTestConditionalFormatting; +import org.apache.poi.ss.usermodel.Color; import org.apache.poi.xssf.XSSFITestDataProvider; /** - * @author Yegor Kozlov + * XSSF-specific Conditional Formatting tests */ public class TestXSSFConditionalFormatting extends BaseTestConditionalFormatting { public TestXSSFConditionalFormatting(){ super(XSSFITestDataProvider.instance); } + protected void assertColour(String hexExpected, Color actual) { + assertNotNull("Colour must be given", actual); + XSSFColor colour = (XSSFColor)actual; + if (hexExpected.length() == 8) { + assertEquals(hexExpected, colour.getARGBHex()); + } else { + assertEquals(hexExpected, colour.getARGBHex().substring(2)); + } + } + public void testRead(){ testRead("WithConditionalFormatting.xlsx"); } + + public void testReadOffice2007() { + testReadOffice2007("NewStyleConditionalFormattings.xlsx"); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFont.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFont.java index 3bbe6f278..e0dbcaa9b 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFont.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFont.java @@ -17,6 +17,8 @@ package org.apache.poi.xssf.usermodel; +import java.io.IOException; + import org.apache.poi.POIXMLException; import org.apache.poi.ss.usermodel.BaseTestFont; import org.apache.poi.ss.usermodel.Font; @@ -25,6 +27,8 @@ import org.apache.poi.ss.usermodel.FontFamily; import org.apache.poi.ss.usermodel.FontScheme; import org.apache.poi.ss.usermodel.FontUnderline; import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.SheetUtil; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBooleanProperty; @@ -88,6 +92,8 @@ public final class TestXSSFFont extends BaseTestFont{ // And set with the Charset index xssfFont.setCharSet(FontCharset.ARABIC.getValue()); assertEquals(FontCharset.ARABIC.getValue(), xssfFont.getCharSet()); + xssfFont.setCharSet((byte)(FontCharset.ARABIC.getValue())); + assertEquals(FontCharset.ARABIC.getValue(), xssfFont.getCharSet()); // This one isn't allowed assertEquals(null, FontCharset.valueOf(9999)); @@ -279,4 +285,23 @@ public final class TestXSSFFont extends BaseTestFont{ font.setTypeOffset(XSSFFont.SS_SUPER); assertEquals(STVerticalAlignRun.SUPERSCRIPT,ctFont.getVertAlignArray(0).getVal()); } + + // store test from TestSheetUtil here as it uses XSSF + public void testCanComputeWidthXSSF() throws IOException { + Workbook wb = new XSSFWorkbook(); + + // cannot check on result because on some machines we get back false here! + SheetUtil.canComputeColumnWidht(wb.getFontAt((short)0)); + + wb.close(); + } + + // store test from TestSheetUtil here as it uses XSSF + public void testCanComputeWidthInvalidFont() throws IOException { + Font font = new XSSFFont(CTFont.Factory.newInstance()); + font.setFontName("some non existing font name"); + + // Even with invalid fonts we still get back useful data most of the time... + SheetUtil.canComputeColumnWidht(font); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java index c2a7597d3..d56005a57 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java @@ -25,6 +25,7 @@ import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.ss.usermodel.BaseTestFormulaEvaluator; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.FormulaError; import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; @@ -186,28 +187,32 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { // Link and re-try Workbook alt = new XSSFWorkbook(); - alt.createSheet().createRow(0).createCell(0).setCellValue("In another workbook"); - // TODO Implement the rest of this, see bug #57184 -/* - wb.linkExternalWorkbook("alt.xlsx", alt); - - cXSLX_nw_cell.setCellFormula("[alt.xlsx]Sheet1!$A$1"); - // Check it - TODO Is this correct? Or should it become [3]Sheet1!$A$1 ? - assertEquals("[alt.xlsx]Sheet1!$A$1", cXSLX_nw_cell.getCellFormula()); - - // Evaluate it, without a link to that workbook try { + alt.createSheet().createRow(0).createCell(0).setCellValue("In another workbook"); + // TODO Implement the rest of this, see bug #57184 +/* + wb.linkExternalWorkbook("alt.xlsx", alt); + + cXSLX_nw_cell.setCellFormula("[alt.xlsx]Sheet1!$A$1"); + // Check it - TODO Is this correct? Or should it become [3]Sheet1!$A$1 ? + assertEquals("[alt.xlsx]Sheet1!$A$1", cXSLX_nw_cell.getCellFormula()); + + // Evaluate it, without a link to that workbook + try { + evaluator.evaluate(cXSLX_nw_cell); + fail("No cached value and no link to workbook, shouldn't evaluate"); + } catch(Exception e) {} + + // Add a link, check it does + evaluators.put("alt.xlsx", alt.getCreationHelper().createFormulaEvaluator()); + evaluator.setupReferencedWorkbooks(evaluators); + evaluator.evaluate(cXSLX_nw_cell); - fail("No cached value and no link to workbook, shouldn't evaluate"); - } catch(Exception e) {} - - // Add a link, check it does - evaluators.put("alt.xlsx", alt.getCreationHelper().createFormulaEvaluator()); - evaluator.setupReferencedWorkbooks(evaluators); - - evaluator.evaluate(cXSLX_nw_cell); - assertEquals("In another workbook", cXSLX_nw_cell.getStringCellValue()); + assertEquals("In another workbook", cXSLX_nw_cell.getStringCellValue()); */ + } finally { + alt.close(); + } } /** @@ -519,7 +524,6 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { } } - public void testBug55843f() throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); try { @@ -539,4 +543,68 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { wb.close(); } } + + public void testBug56655() throws IOException { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet(); + + setCellFormula(sheet, 0, 0, "#VALUE!"); + setCellFormula(sheet, 0, 1, "SUMIFS(A:A,A:A,#VALUE!)"); + + wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); + + assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 0,0).getCachedFormulaResultType()); + assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0,0).getErrorCellValue()); + assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 0,1).getCachedFormulaResultType()); + assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0,1).getErrorCellValue()); + + wb.close(); + } + + public void testBug56655a() throws IOException { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet(); + + setCellFormula(sheet, 0, 0, "B1*C1"); + sheet.getRow(0).createCell(1).setCellValue("A"); + setCellFormula(sheet, 1, 0, "B1*C1"); + sheet.getRow(1).createCell(1).setCellValue("A"); + setCellFormula(sheet, 0, 3, "SUMIFS(A:A,A:A,A2)"); + + wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); + + assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 0, 0).getCachedFormulaResultType()); + assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0, 0).getErrorCellValue()); + assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 1, 0).getCachedFormulaResultType()); + assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 1, 0).getErrorCellValue()); + assertEquals(XSSFCell.CELL_TYPE_ERROR, getCell(sheet, 0, 3).getCachedFormulaResultType()); + assertEquals(FormulaError.VALUE.getCode(), getCell(sheet, 0, 3).getErrorCellValue()); + + wb.close(); + } + + /** + * @param row 0-based + * @param column 0-based + */ + private void setCellFormula(Sheet sheet, int row, int column, String formula) { + Row r = sheet.getRow(row); + if (r == null) { + r = sheet.createRow(row); + } + Cell cell = r.getCell(column); + if (cell == null) { + cell = r.createCell(column); + } + cell.setCellType(XSSFCell.CELL_TYPE_FORMULA); + cell.setCellFormula(formula); + } + + /** + * @param rowNo 0-based + * @param column 0-based + */ + private Cell getCell(Sheet sheet, int rowNo, int column) { + return sheet.getRow(rowNo).getCell(column); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java index fe06afcd8..df5681939 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java @@ -92,8 +92,8 @@ public final class TestXSSFPictureData extends TestCase { assertNotNull(p3); //check that the added pictures are accessible after write - wb = XSSFTestDataSamples.writeOutAndReadBack(wb); - List pictures2 = wb.getAllPictures(); + XSSFWorkbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb); + List pictures2 = wbBack.getAllPictures(); assertEquals(3, pictures2.size()); assertEquals("jpeg", pictures2.get(jpegIdx).suggestFileExtension()); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPrintSetup.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPrintSetup.java index 3001197cd..6cda3aff2 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPrintSetup.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPrintSetup.java @@ -19,12 +19,18 @@ package org.apache.poi.xssf.usermodel; import junit.framework.TestCase; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; -import org.apache.poi.ss.usermodel.PaperSize; import org.apache.poi.ss.usermodel.PageOrder; -import org.apache.poi.ss.usermodel.PrintOrientation; +import org.apache.poi.ss.usermodel.PaperSize; import org.apache.poi.ss.usermodel.PrintCellComments; +import org.apache.poi.ss.usermodel.PrintOrientation; import org.apache.poi.xssf.XSSFITestDataProvider; +import org.junit.Test; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageSetup; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellComments; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STOrientation; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPageOrder; /** * Tests for {@link XSSFPrintSetup} @@ -226,10 +232,10 @@ public class TestXSSFPrintSetup extends TestCase { assertEquals(true, s2.getCTWorksheet().isSetPageMargins()); // Round trip and check - wb = XSSFITestDataProvider.instance.writeOutAndReadBack(wb); + XSSFWorkbook wbBack = XSSFITestDataProvider.instance.writeOutAndReadBack(wb); - s1 = wb.getSheetAt(0); - s2 = wb.getSheetAt(1); + s1 = wbBack.getSheetAt(0); + s2 = wbBack.getSheetAt(1); assertEquals(true, s1.getCTWorksheet().isSetPageSetup()); assertEquals(true, s1.getCTWorksheet().isSetPageMargins()); @@ -239,6 +245,8 @@ public class TestXSSFPrintSetup extends TestCase { print = s1.getPrintSetup(); assertEquals(3, print.getCopies()); assertEquals(true, print.getLandscape()); + + wb.close(); } /** @@ -248,4 +256,30 @@ public class TestXSSFPrintSetup extends TestCase { public void testRoundTrip() { // TODO } + + @Test + public void testSetLandscapeFalse() throws Exception { + XSSFPrintSetup ps = new XSSFPrintSetup(CTWorksheet.Factory.newInstance()); + + assertFalse(ps.getLandscape()); + + ps.setLandscape(true); + assertTrue(ps.getLandscape()); + + ps.setLandscape(false); + assertFalse(ps.getLandscape()); + } + + @Test + public void testSetLeftToRight() throws Exception { + XSSFPrintSetup ps = new XSSFPrintSetup(CTWorksheet.Factory.newInstance()); + + assertFalse(ps.getLeftToRight()); + + ps.setLeftToRight(true); + assertTrue(ps.getLeftToRight()); + + ps.setLeftToRight(false); + assertFalse(ps.getLeftToRight()); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java index d8f56f84e..785af694d 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java @@ -36,21 +36,17 @@ import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.ss.usermodel.AutoFilter; import org.apache.poi.ss.usermodel.BaseTestSheet; import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CreationHelper; -import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellReference; -import org.apache.poi.xssf.SXSSFITestDataProvider; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.model.CalculationChain; import org.apache.poi.xssf.model.CommentsTable; import org.apache.poi.xssf.model.StylesTable; -import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.helpers.ColumnHelper; import org.junit.Test; @@ -60,8 +56,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; @SuppressWarnings("resource") public final class TestXSSFSheet extends BaseTestSheet { - private static final int ROW_COUNT = 40000; - public TestXSSFSheet() { super(XSSFITestDataProvider.instance); } @@ -188,39 +182,6 @@ public final class TestXSSFSheet extends BaseTestSheet { assertTrue(col.getBestFit()); } - /** - * XSSFSheet autoSizeColumn() on empty RichTextString fails - */ - @Test - public void bug48325() { - XSSFWorkbook wb = new XSSFWorkbook(); - XSSFSheet sheet = wb.createSheet("Test"); - CreationHelper factory = wb.getCreationHelper(); - - XSSFRow row = sheet.createRow(0); - XSSFCell cell = row.createCell(0); - - XSSFFont font = wb.createFont(); - RichTextString rts = factory.createRichTextString(""); - rts.applyFont(font); - cell.setCellValue(rts); - - sheet.autoSizeColumn(0); - } - - @Test - public void getCellComment() { - XSSFWorkbook workbook = new XSSFWorkbook(); - XSSFSheet sheet = workbook.createSheet(); - XSSFDrawing dg = sheet.createDrawingPatriarch(); - XSSFComment comment = dg.createCellComment(new XSSFClientAnchor()); - XSSFCell cell = sheet.createRow(9).createCell(2); - comment.setAuthor("test C10 author"); - cell.setCellComment(comment); - - assertNotNull(sheet.getCellComment(9, 2)); - assertEquals("test C10 author", sheet.getCellComment(9, 2).getAuthor()); - } @Test public void setCellComment() { @@ -268,16 +229,6 @@ public final class TestXSSFSheet extends BaseTestSheet { assertEquals(STPane.BOTTOM_RIGHT, ctWorksheet.getSheetViews().getSheetViewArray(0).getPane().getActivePane()); } - @Test - public void newMergedRegionAt() { - XSSFWorkbook workbook = new XSSFWorkbook(); - XSSFSheet sheet = workbook.createSheet(); - CellRangeAddress region = CellRangeAddress.valueOf("B2:D4"); - sheet.addMergedRegion(region); - assertEquals("B2:D4", sheet.getMergedRegion(0).formatAsString()); - assertEquals(1, sheet.getNumMergedRegions()); - } - @Test public void removeMergedRegion_lowlevel() { XSSFWorkbook workbook = new XSSFWorkbook(); @@ -1244,53 +1195,6 @@ public final class TestXSSFSheet extends BaseTestSheet { } } - @Test - public void showInPaneManyRowsBug55248() { - XSSFWorkbook workbook = new XSSFWorkbook(); - XSSFSheet sheet = workbook.createSheet("Sheet 1"); - - sheet.showInPane(0, 0); - - for(int i = ROW_COUNT/2;i < ROW_COUNT;i++) { - sheet.createRow(i); - sheet.showInPane(i, 0); - // this one fails: sheet.showInPane((short)i, 0); - } - - int i = 0; - sheet.showInPane(i, i); - - XSSFWorkbook wb = XSSFTestDataSamples.writeOutAndReadBack(workbook); - checkRowCount(wb); - } - - @Test - public void showInPaneManyRowsBug55248SXSSF() { - SXSSFWorkbook workbook = new SXSSFWorkbook(new XSSFWorkbook()); - SXSSFSheet sheet = (SXSSFSheet) workbook.createSheet("Sheet 1"); - - sheet.showInPane(0, 0); - - for(int i = ROW_COUNT/2;i < ROW_COUNT;i++) { - sheet.createRow(i); - sheet.showInPane(i, 0); - // this one fails: sheet.showInPane((short)i, 0); - } - - int i = 0; - sheet.showInPane(i, i); - - Workbook wb = SXSSFITestDataProvider.instance.writeOutAndReadBack(workbook); - checkRowCount(wb); - } - - private void checkRowCount(Workbook wb) { - assertNotNull(wb); - final Sheet sh = wb.getSheet("Sheet 1"); - assertNotNull(sh); - assertEquals(ROW_COUNT-1, sh.getLastRowNum()); - } - @Test public void bug55745() throws Exception { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("55745.xlsx"); @@ -1472,16 +1376,4 @@ public final class TestXSSFSheet extends BaseTestSheet { XSSFSheet sheet = wb.createSheet(); assertNotNull(sheet.createComment()); } - - @Test - public void testRightToLeft() { - XSSFWorkbook wb = new XSSFWorkbook(); - XSSFSheet sheet = wb.createSheet(); - - assertFalse(sheet.isRightToLeft()); - sheet.setRightToLeft(true); - assertTrue(sheet.isRightToLeft()); - sheet.setRightToLeft(false); - assertFalse(sheet.isRightToLeft()); - } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetMergeRegions.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetMergeRegions.java new file mode 100644 index 000000000..416c6217b --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetMergeRegions.java @@ -0,0 +1,48 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.xssf.usermodel; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.List; + +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.XSSFTestDataSamples; +import org.junit.Test; + +public class TestXSSFSheetMergeRegions { + @Test + public void testMergeRegionsSpeed() throws IOException { + final XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("57893-many-merges.xlsx"); + try { + final XSSFSheet sheet = wb.getSheetAt(0); + final long start = System.currentTimeMillis(); + final List mergedRegions = sheet.getMergedRegions(); + assertEquals(50000, mergedRegions.size()); + for (CellRangeAddress cellRangeAddress : mergedRegions) { + assertEquals(cellRangeAddress.getFirstRow(), cellRangeAddress.getLastRow()); + assertEquals(2, cellRangeAddress.getNumberOfCells()); + } + long millis = System.currentTimeMillis() - start; + // This time is typically ~800ms, versus ~7800ms to iterate getMergedRegion(int). + assertTrue("Should have taken <2000 ms to iterate 50k merged regions but took " + millis, millis < 2000); + } finally { + wb.close(); + } + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java index e949dd13d..89364463b 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java @@ -25,7 +25,6 @@ import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellUtil; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; @@ -44,11 +43,6 @@ public final class TestXSSFSheetShiftRows extends BaseTestSheetShiftRows { // TODO - support shifting of page breaks } - @Override - public void testShiftWithComments() { // disabled test from superclass - // TODO - support shifting of comments. - } - public void testBug54524() throws IOException { XSSFWorkbook workbook = XSSFTestDataSamples.openSampleWorkbook("54524.xlsx"); XSSFSheet sheet = workbook.getSheetAt(0); @@ -61,7 +55,6 @@ public final class TestXSSFSheetShiftRows extends BaseTestSheetShiftRows { cell = CellUtil.getCell(sheet.getRow(3), 0); assertEquals("X", cell.getStringCellValue()); } - public void testBug53798() throws IOException { // NOTE that for HSSF (.xls) negative shifts combined with positive ones do work as expected @@ -189,19 +182,6 @@ public final class TestXSSFSheetShiftRows extends BaseTestSheetShiftRows { assertEquals("Amdocs:\ntest\n", comment.getString().getString()); } - public void testBug55280() throws IOException { - Workbook w = new XSSFWorkbook(); - try { - Sheet s = w.createSheet(); - for (int row = 0; row < 5000; ++row) - s.addMergedRegion(new CellRangeAddress(row, row, 0, 3)); - - s.shiftRows(0, 4999, 1); // takes a long time... - } finally { - w.close(); - } - } - public void test57171() throws Exception { Workbook wb = XSSFTestDataSamples.openSampleWorkbook("57171_57163_57165.xlsx"); assertEquals(5, wb.getActiveSheetIndex()); @@ -352,4 +332,38 @@ public final class TestXSSFSheetShiftRows extends BaseTestSheetShiftRows { wb.removeSheetAt(sn); } } + + public void testBug57828_OnlyOneCommentShiftedInRow() throws IOException { + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("57828.xlsx"); + XSSFSheet sheet = wb.getSheetAt(0); + + Comment comment1 = sheet.getCellComment(2, 1); + assertNotNull(comment1); + + Comment comment2 = sheet.getCellComment(2, 2); + assertNotNull(comment2); + + Comment comment3 = sheet.getCellComment(1, 1); + assertNull("NO comment in (1,1) and it should be null", comment3); + + sheet.shiftRows(2, 2, -1); + + comment3 = sheet.getCellComment(1, 1); + assertNotNull("Comment in (2,1) moved to (1,1) so its not null now.", comment3); + + comment1 = sheet.getCellComment(2, 1); + assertNull("No comment currently in (2,1) and hence it is null", comment1); + + comment2 = sheet.getCellComment(1, 2); + assertNotNull("Comment in (2,2) should have moved as well because of shift rows. But its not", comment2); + +// OutputStream stream = new FileOutputStream("/tmp/57828.xlsx"); +// try { +// wb.write(stream); +// } finally { +// stream.close(); +// } + + wb.close(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java index 346abe079..5bb3acd0f 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFVMLDrawing.java @@ -54,14 +54,14 @@ public class TestXSSFVMLDrawing extends TestCase { assertEquals("21600,21600", type.getCoordsize()); assertEquals(202.0f, type.getSpt()); assertEquals("m,l,21600r21600,l21600,xe", type.getPath2()); - assertEquals("_xssf_cell_comment", type.getId()); + assertEquals("_x0000_t202", type.getId()); assertEquals(STTrueFalse.T, type.getPathArray(0).getGradientshapeok()); assertEquals(STConnectType.RECT, type.getPathArray(0).getConnecttype()); CTShape shape = vml.newCommentShape(); assertEquals(3, items.size()); assertSame(items.get(2), shape); - assertEquals("#_xssf_cell_comment", shape.getType()); + assertEquals("#_x0000_t202", shape.getType()); assertEquals("position:absolute; visibility:hidden", shape.getStyle()); assertEquals("#ffffe1", shape.getFillcolor()); assertEquals(STInsetMode.AUTO, shape.getInsetmode()); diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java index 209bded8c..392ab906e 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java @@ -17,6 +17,7 @@ package org.apache.poi.xssf.usermodel; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -25,6 +26,7 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -39,10 +41,11 @@ import org.apache.poi.openxml4j.opc.ContentTypes; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; - +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.BaseTestWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -78,7 +81,8 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook { */ @Test public void saveLoadNew() throws Exception { - XSSFWorkbook workbook = new XSSFWorkbook(); + @SuppressWarnings("resource") + XSSFWorkbook workbook = new XSSFWorkbook(); //check that the default date system is set to 1900 CTWorkbookPr pr = workbook.getCTWorkbook().getWorkbookPr(); @@ -121,7 +125,8 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook { // Links to the three sheets, shared strings and styles assertTrue(wbPart.hasRelationships()); assertEquals(5, wbPart.getRelationships().size()); - + workbook.close(); + // Load back the XSSFWorkbook workbook = new XSSFWorkbook(pkg); assertEquals(3, workbook.getNumberOfSheets()); @@ -777,7 +782,7 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook { Cell cell9 = row3.createCell(2); cell9.setCellValue("Bepa"); - AreaReference source = new AreaReference("A1:B2"); + AreaReference source = new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007); sheet.createPivotTable(source, new CellReference("H5")); } @@ -869,4 +874,54 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook { wb.close(); } } + + /** + * Tests that we can save a workbook with macros and reload it. + */ + @Test + public void testSetVBAProject() throws Exception { + XSSFWorkbook workbook = null; + OutputStream out = null; + File file; + final byte[] allBytes = new byte[256]; + for (int i = 0; i < 256; i++) { + allBytes[i] = (byte) (i - 128); + } + try { + workbook = new XSSFWorkbook(); + workbook.createSheet(); + workbook.setVBAProject(new ByteArrayInputStream(allBytes)); + file = TempFile.createTempFile("poi-", ".xlsm"); + out = new FileOutputStream(file); + workbook.write(out); + } + finally { + IOUtils.closeQuietly(out); + IOUtils.closeQuietly(workbook); + } + + try { + // Check the package contains what we'd expect it to + OPCPackage pkg = OPCPackage.open(file.toString()); + PackagePart wbPart = pkg.getPart(PackagingURIHelper.createPartName("/xl/workbook.xml")); + assertTrue(wbPart.hasRelationships()); + final PackageRelationshipCollection relationships = wbPart.getRelationships().getRelationships(XSSFRelation.VBA_MACROS.getRelation()); + assertEquals(1, relationships.size()); + assertEquals(XSSFRelation.VBA_MACROS.getDefaultFileName(), relationships.getRelationship(0).getTargetURI().toString()); + PackagePart vbaPart = pkg.getPart(PackagingURIHelper.createPartName(XSSFRelation.VBA_MACROS.getDefaultFileName())); + assertNotNull(vbaPart); + assertFalse(vbaPart.isRelationshipPart()); + assertEquals(XSSFRelation.VBA_MACROS.getContentType(), vbaPart.getContentType()); + final byte[] fromFile = IOUtils.toByteArray(vbaPart.getInputStream()); + assertArrayEquals(allBytes, fromFile); + + // Load back the XSSFWorkbook just to check nothing explodes + workbook = new XSSFWorkbook(pkg); + assertEquals(1, workbook.getNumberOfSheets()); + assertEquals(XSSFWorkbookType.XLSM, workbook.getWorkbookType()); + } + finally { + IOUtils.closeQuietly(workbook); + } + } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/AllXWPFTests.java b/src/ooxml/testcases/org/apache/poi/xwpf/AllXWPFTests.java index f7ed6df7c..7243f114d 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/AllXWPFTests.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/AllXWPFTests.java @@ -33,24 +33,24 @@ import org.junit.runners.Suite; /** * Collects all tests for org.apache.poi.xwpf and sub-packages. - */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - TestXWPFBugs.class, - org.apache.poi.xwpf.usermodel.TestXWPFBugs.class, - TestXWPFDocument.class, - TestXWPFWordExtractor.class, - TestXWPFHeaderFooterPolicy.class, - TestXWPFHeader.class, - TestXWPFHeadings.class, - TestXWPFParagraph.class, - TestXWPFRun.class, - TestXWPFTable.class, - TestXWPFStyles.class, - TestXWPFPictureData.class, - TestXWPFNumbering.class, - TestAllExtendedProperties.class, - TestPackageCorePropertiesGetKeywords.class -}) -public final class AllXWPFTests { + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestXWPFBugs.class, + org.apache.poi.xwpf.usermodel.TestXWPFBugs.class, + TestXWPFDocument.class, + TestXWPFWordExtractor.class, + TestXWPFHeaderFooterPolicy.class, + TestXWPFHeader.class, + TestXWPFHeadings.class, + TestXWPFParagraph.class, + TestXWPFRun.class, + TestXWPFTable.class, + TestXWPFStyles.class, + TestXWPFPictureData.class, + TestXWPFNumbering.class, + TestAllExtendedProperties.class, + TestPackageCorePropertiesGetKeywords.class +}) +public final class AllXWPFTests { } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/TestAllExtendedProperties.java b/src/ooxml/testcases/org/apache/poi/xwpf/TestAllExtendedProperties.java index c04f73c93..ff955dadb 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/TestAllExtendedProperties.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/TestAllExtendedProperties.java @@ -17,13 +17,12 @@ package org.apache.poi.xwpf; -import java.io.IOException; - -import junit.framework.TestCase; - -import org.apache.poi.POIXMLProperties.CoreProperties; -import org.apache.poi.openxml4j.opc.PackageProperties; -import org.apache.poi.xwpf.usermodel.XWPFDocument; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.POIXMLProperties.CoreProperties; +import org.apache.poi.openxml4j.opc.PackageProperties; +import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTDigSigBlob; import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties; import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTVectorLpstr; @@ -31,77 +30,76 @@ import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTVect /** * Tests if the {@link CoreProperties#getKeywords()} method. This test has been - * submitted because even though the - * {@link PackageProperties#getKeywordsProperty()} had been present before, the - * {@link CoreProperties#getKeywords()} had been missing. - * - * The author of this has added {@link CoreProperties#getKeywords()} and - * {@link CoreProperties#setKeywords(String)} and this test is supposed to test - * them. - * - * @author Antoni Mylka - * - */ -public final class TestAllExtendedProperties extends TestCase { - public void testGetAllExtendedProperties() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestPoiXMLDocumentCorePropertiesGetKeywords.docx"); - CTProperties ctProps = doc.getProperties().getExtendedProperties().getUnderlyingProperties(); - assertEquals("Microsoft Office Word",ctProps.getApplication()); - assertEquals("14.0000",ctProps.getAppVersion()); - assertEquals(57,ctProps.getCharacters()); - assertEquals(66,ctProps.getCharactersWithSpaces()); - assertEquals("",ctProps.getCompany()); - assertNull(ctProps.getDigSig()); - assertEquals(0,ctProps.getDocSecurity()); - assertNotNull(ctProps.getDomNode()); - - CTVectorVariant vec = ctProps.getHeadingPairs(); - assertEquals(2,vec.getVector().sizeOfVariantArray()); - assertEquals("Title",vec.getVector().getVariantArray(0).getLpstr()); - assertEquals(1,vec.getVector().getVariantArray(1).getI4()); - - assertFalse(ctProps.isSetHiddenSlides()); - assertEquals(0,ctProps.getHiddenSlides()); - assertFalse(ctProps.isSetHLinks()); - assertNull(ctProps.getHLinks()); - assertNull(ctProps.getHyperlinkBase()); - assertTrue(ctProps.isSetHyperlinksChanged()); - assertFalse(ctProps.getHyperlinksChanged()); - assertEquals(1,ctProps.getLines()); - assertTrue(ctProps.isSetLinksUpToDate()); - assertFalse(ctProps.getLinksUpToDate()); - assertNull(ctProps.getManager()); - assertFalse(ctProps.isSetMMClips()); - assertEquals(0,ctProps.getMMClips()); - assertFalse(ctProps.isSetNotes()); - assertEquals(0,ctProps.getNotes()); - assertEquals(1,ctProps.getPages()); - assertEquals(1,ctProps.getParagraphs()); - assertNull(ctProps.getPresentationFormat()); - assertTrue(ctProps.isSetScaleCrop()); - assertFalse(ctProps.getScaleCrop()); - assertTrue(ctProps.isSetSharedDoc()); - assertFalse(ctProps.getSharedDoc()); - assertFalse(ctProps.isSetSlides()); - assertEquals(0,ctProps.getSlides()); - assertEquals("Normal.dotm",ctProps.getTemplate()); - - CTVectorLpstr vec2 = ctProps.getTitlesOfParts(); - assertEquals(1,vec2.getVector().sizeOfLpstrArray()); - assertEquals("Example Word 2010 Document",vec2.getVector().getLpstrArray(0)); - - assertEquals(3,ctProps.getTotalTime()); - assertEquals(10,ctProps.getWords()); - - // Check the digital signature part - // Won't be there in this file, but we - // need to do this check so that the - // appropriate parts end up in the - // smaller ooxml schemas file - CTDigSigBlob blob = ctProps.getDigSig(); - assertNull(blob); - - blob = CTDigSigBlob.Factory.newInstance(); - blob.setBlob(new byte [] {2,6,7,2,3,4,5,1,2,3}); - } -} + * submitted because even though the + * {@link PackageProperties#getKeywordsProperty()} had been present before, the + * {@link CoreProperties#getKeywords()} had been missing. + *

    + * The author of this has added {@link CoreProperties#getKeywords()} and + * {@link CoreProperties#setKeywords(String)} and this test is supposed to test + * them. + * + * @author Antoni Mylka + */ +public final class TestAllExtendedProperties extends TestCase { + public void testGetAllExtendedProperties() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestPoiXMLDocumentCorePropertiesGetKeywords.docx"); + CTProperties ctProps = doc.getProperties().getExtendedProperties().getUnderlyingProperties(); + assertEquals("Microsoft Office Word", ctProps.getApplication()); + assertEquals("14.0000", ctProps.getAppVersion()); + assertEquals(57, ctProps.getCharacters()); + assertEquals(66, ctProps.getCharactersWithSpaces()); + assertEquals("", ctProps.getCompany()); + assertNull(ctProps.getDigSig()); + assertEquals(0, ctProps.getDocSecurity()); + assertNotNull(ctProps.getDomNode()); + + CTVectorVariant vec = ctProps.getHeadingPairs(); + assertEquals(2, vec.getVector().sizeOfVariantArray()); + assertEquals("Title", vec.getVector().getVariantArray(0).getLpstr()); + assertEquals(1, vec.getVector().getVariantArray(1).getI4()); + + assertFalse(ctProps.isSetHiddenSlides()); + assertEquals(0, ctProps.getHiddenSlides()); + assertFalse(ctProps.isSetHLinks()); + assertNull(ctProps.getHLinks()); + assertNull(ctProps.getHyperlinkBase()); + assertTrue(ctProps.isSetHyperlinksChanged()); + assertFalse(ctProps.getHyperlinksChanged()); + assertEquals(1, ctProps.getLines()); + assertTrue(ctProps.isSetLinksUpToDate()); + assertFalse(ctProps.getLinksUpToDate()); + assertNull(ctProps.getManager()); + assertFalse(ctProps.isSetMMClips()); + assertEquals(0, ctProps.getMMClips()); + assertFalse(ctProps.isSetNotes()); + assertEquals(0, ctProps.getNotes()); + assertEquals(1, ctProps.getPages()); + assertEquals(1, ctProps.getParagraphs()); + assertNull(ctProps.getPresentationFormat()); + assertTrue(ctProps.isSetScaleCrop()); + assertFalse(ctProps.getScaleCrop()); + assertTrue(ctProps.isSetSharedDoc()); + assertFalse(ctProps.getSharedDoc()); + assertFalse(ctProps.isSetSlides()); + assertEquals(0, ctProps.getSlides()); + assertEquals("Normal.dotm", ctProps.getTemplate()); + + CTVectorLpstr vec2 = ctProps.getTitlesOfParts(); + assertEquals(1, vec2.getVector().sizeOfLpstrArray()); + assertEquals("Example Word 2010 Document", vec2.getVector().getLpstrArray(0)); + + assertEquals(3, ctProps.getTotalTime()); + assertEquals(10, ctProps.getWords()); + + // Check the digital signature part + // Won't be there in this file, but we + // need to do this check so that the + // appropriate parts end up in the + // smaller ooxml schemas file + CTDigSigBlob blob = ctProps.getDigSig(); + assertNull(blob); + + blob = CTDigSigBlob.Factory.newInstance(); + blob.setBlob(new byte[]{2, 6, 7, 2, 3, 4, 5, 1, 2, 3}); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/TestPackageCorePropertiesGetKeywords.java b/src/ooxml/testcases/org/apache/poi/xwpf/TestPackageCorePropertiesGetKeywords.java index 4b37623df..85a21f12b 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/TestPackageCorePropertiesGetKeywords.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/TestPackageCorePropertiesGetKeywords.java @@ -17,36 +17,34 @@ package org.apache.poi.xwpf; -import java.io.IOException; - -import junit.framework.TestCase; - -import org.apache.poi.POIXMLProperties.CoreProperties; -import org.apache.poi.openxml4j.opc.PackageProperties; -import org.apache.poi.xwpf.usermodel.XWPFDocument; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.POIXMLProperties.CoreProperties; +import org.apache.poi.openxml4j.opc.PackageProperties; +import org.apache.poi.xwpf.usermodel.XWPFDocument; /** * Tests if the {@link CoreProperties#getKeywords()} method. This test has been - * submitted because even though the - * {@link PackageProperties#getKeywordsProperty()} had been present before, the - * {@link CoreProperties#getKeywords()} had been missing. - * - * The author of this has added {@link CoreProperties#getKeywords()} and - * {@link CoreProperties#setKeywords(String)} and this test is supposed to test - * them. - * - * @author Antoni Mylka - * - */ -public final class TestPackageCorePropertiesGetKeywords extends TestCase { - public void testGetSetKeywords() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestPoiXMLDocumentCorePropertiesGetKeywords.docx"); - String keywords = doc.getProperties().getCoreProperties().getKeywords(); - assertEquals("extractor, test, rdf", keywords); - - doc.getProperties().getCoreProperties().setKeywords("test, keywords"); - doc = XWPFTestDataSamples.writeOutAndReadBack(doc); - keywords = doc.getProperties().getCoreProperties().getKeywords(); - assertEquals("test, keywords",keywords); - } -} + * submitted because even though the + * {@link PackageProperties#getKeywordsProperty()} had been present before, the + * {@link CoreProperties#getKeywords()} had been missing. + *

    + * The author of this has added {@link CoreProperties#getKeywords()} and + * {@link CoreProperties#setKeywords(String)} and this test is supposed to test + * them. + * + * @author Antoni Mylka + */ +public final class TestPackageCorePropertiesGetKeywords extends TestCase { + public void testGetSetKeywords() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestPoiXMLDocumentCorePropertiesGetKeywords.docx"); + String keywords = doc.getProperties().getCoreProperties().getKeywords(); + assertEquals("extractor, test, rdf", keywords); + + doc.getProperties().getCoreProperties().setKeywords("test, keywords"); + doc = XWPFTestDataSamples.writeOutAndReadBack(doc); + keywords = doc.getProperties().getCoreProperties().getKeywords(); + assertEquals("test, keywords", keywords); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java b/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java index 055e47076..6f7e4b689 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java @@ -40,7 +40,7 @@ import org.junit.Test; public class TestXWPFBugs { /** * A word document that's encrypted with non-standard - * Encryption options, and no cspname section. See bug 53475 + * Encryption options, and no cspname section. See bug 53475 */ @Test public void bug53475NoCSPName() throws Exception { @@ -54,7 +54,7 @@ public class TestXWPFBugs { assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithmEx()); // Check it can be decoded - Decryptor d = Decryptor.getInstance(info); + Decryptor d = Decryptor.getInstance(info); assertTrue("Unable to process: document is encrypted", d.verifyPassword("solrcell")); // Check we can read the word document in that @@ -66,7 +66,7 @@ public class TestXWPFBugs { assertNotNull(text); assertEquals("This is password protected Word document.", text.trim()); ex.close(); - + filesystem.close(); } @@ -90,7 +90,7 @@ public class TestXWPFBugs { assertEquals(HashAlgorithm.sha1, info.getHeader().getHashAlgorithmEx()); // Check it can be decoded - Decryptor d = Decryptor.getInstance(info); + Decryptor d = Decryptor.getInstance(info); assertTrue("Unable to process: document is encrypted", d.verifyPassword("pass")); // Check we can read the word document in that @@ -103,7 +103,7 @@ public class TestXWPFBugs { // I know ... a stupid typo, maybe next time ... assertEquals("The is a password protected document.", text.trim()); ex.close(); - + filesystem.close(); } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestExternalEntities.java b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestExternalEntities.java index 05d6b2f84..929d43041 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestExternalEntities.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestExternalEntities.java @@ -20,7 +20,6 @@ package org.apache.poi.xwpf.extractor; import java.io.IOException; import junit.framework.TestCase; - import org.apache.poi.xwpf.XWPFTestDataSamples; import org.apache.poi.xwpf.usermodel.XWPFDocument; @@ -28,19 +27,20 @@ public class TestExternalEntities extends TestCase { /** * Get text out of the simple file - * @throws IOException + * + * @throws IOException */ public void testFile() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("ExternalEntityInText.docx"); XWPFWordExtractor extractor = new XWPFWordExtractor(doc); String text = extractor.getText(); - + assertTrue(text.length() > 0); // Check contents, they should not contain the text from POI web site after colon! assertEquals("Here should not be the POI web site: \"\"", text.trim()); - + extractor.close(); } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java index 00408829d..48330bbee 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java @@ -22,7 +22,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import junit.framework.TestCase; - import org.apache.poi.xwpf.XWPFTestDataSamples; import org.apache.poi.xwpf.usermodel.XWPFDocument; @@ -33,7 +32,8 @@ public class TestXWPFWordExtractor extends TestCase { /** * Get text out of the simple file - * @throws IOException + * + * @throws IOException */ public void testGetSimpleText() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); @@ -59,13 +59,14 @@ public class TestXWPFWordExtractor extends TestCase { } } assertEquals(3, ps); - + extractor.close(); } /** * Tests getting the text out of a complex file - * @throws IOException + * + * @throws IOException */ public void testGetComplexText() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("IllustrativeCases.docx"); @@ -97,7 +98,7 @@ public class TestXWPFWordExtractor extends TestCase { } } assertEquals(134, ps); - + extractor.close(); } @@ -108,23 +109,23 @@ public class TestXWPFWordExtractor extends TestCase { // Now check contents extractor.setFetchHyperlinks(false); assertEquals( - "This is a test document.\nThis bit is in bold and italic\n" + - "Back to normal\n" + - "This contains BOLD, ITALIC and BOTH, as well as RED and YELLOW text.\n" + - "We have a hyperlink here, and another.\n", + "This is a test document.\nThis bit is in bold and italic\n" + + "Back to normal\n" + + "This contains BOLD, ITALIC and BOTH, as well as RED and YELLOW text.\n" + + "We have a hyperlink here, and another.\n", extractor.getText() ); // One hyperlink is a real one, one is just to the top of page extractor.setFetchHyperlinks(true); assertEquals( - "This is a test document.\nThis bit is in bold and italic\n" + - "Back to normal\n" + - "This contains BOLD, ITALIC and BOTH, as well as RED and YELLOW text.\n" + - "We have a hyperlink here, and another.\n", + "This is a test document.\nThis bit is in bold and italic\n" + + "Back to normal\n" + + "This contains BOLD, ITALIC and BOTH, as well as RED and YELLOW text.\n" + + "We have a hyperlink here, and another.\n", extractor.getText() ); - + extractor.close(); } @@ -173,7 +174,7 @@ public class TestXWPFWordExtractor extends TestCase { "Footer Left\tFooter Middle\tFooter Right\n", extractor.getText() ); - + extractor.close(); } @@ -183,7 +184,7 @@ public class TestXWPFWordExtractor extends TestCase { String text = extractor.getText(); assertTrue(text.contains("snoska")); assertTrue(text.contains("Eto ochen prostoy[footnoteRef:1] text so snoskoy")); - + extractor.close(); } @@ -193,7 +194,7 @@ public class TestXWPFWordExtractor extends TestCase { XWPFWordExtractor extractor = new XWPFWordExtractor(doc); assertTrue(extractor.getText().contains("snoska")); - + extractor.close(); } @@ -204,7 +205,7 @@ public class TestXWPFWordExtractor extends TestCase { String text = extractor.getText(); assertTrue("Unable to find expected word in text\n" + text, text.contains("testdoc")); assertTrue("Unable to find expected word in text\n" + text, text.contains("test phrase")); - + extractor.close(); } @@ -214,7 +215,7 @@ public class TestXWPFWordExtractor extends TestCase { String text = extractor.getText(); assertTrue(text.contains("XXX")); assertTrue(text.contains("tilaka [endnoteRef:2]or 'tika'")); - + extractor.close(); } @@ -224,7 +225,7 @@ public class TestXWPFWordExtractor extends TestCase { assertTrue(extractor.getText().contains("pendant worn")); assertTrue(extractor.getText().contains("extremely well")); - + extractor.close(); } @@ -235,14 +236,15 @@ public class TestXWPFWordExtractor extends TestCase { assertTrue(extractor.getText().contains("Section 1")); assertTrue(extractor.getText().contains("Section 2")); assertTrue(extractor.getText().contains("Section 3")); - + extractor.close(); } /** * Test that we can open and process .docm - * (macro enabled) docx files (bug #45690) - * @throws IOException + * (macro enabled) docx files (bug #45690) + * + * @throws IOException */ public void testDOCMFiles() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("45690.docm"); @@ -251,35 +253,37 @@ public class TestXWPFWordExtractor extends TestCase { assertTrue(extractor.getText().contains("2004")); assertTrue(extractor.getText().contains("2008")); assertTrue(extractor.getText().contains("(120 ")); - + extractor.close(); } - + /** * Test that we handle things like tabs and - * carriage returns properly in the text that - * we're extracting (bug #49189) - * @throws IOException + * carriage returns properly in the text that + * we're extracting (bug #49189) + * + * @throws IOException */ public void testDocTabs() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("WithTabs.docx"); - XWPFWordExtractor extractor = new XWPFWordExtractor(doc); - - // Check bits - assertTrue(extractor.getText().contains("a")); - assertTrue(extractor.getText().contains("\t")); - assertTrue(extractor.getText().contains("b")); - - // Now check the first paragraph in total - assertTrue(extractor.getText().contains("a\tb\n")); - - extractor.close(); + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("WithTabs.docx"); + XWPFWordExtractor extractor = new XWPFWordExtractor(doc); + + // Check bits + assertTrue(extractor.getText().contains("a")); + assertTrue(extractor.getText().contains("\t")); + assertTrue(extractor.getText().contains("b")); + + // Now check the first paragraph in total + assertTrue(extractor.getText().contains("a\tb\n")); + + extractor.close(); } - + /** * The output should not contain field codes, e.g. those specified in the * w:instrText tag (spec sec. 17.16.23) - * @throws IOException + * + * @throws IOException */ public void testNoFieldCodes() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("FieldCodes.docx"); @@ -288,14 +292,15 @@ public class TestXWPFWordExtractor extends TestCase { assertTrue(text.length() > 0); assertFalse(text.contains("AUTHOR")); assertFalse(text.contains("CREATEDATE")); - + extractor.close(); } - + /** * The output should contain the values of simple fields, those specified * with the fldSimple element (spec sec. 17.16.19) - * @throws IOException + * + * @throws IOException */ public void testFldSimpleContent() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("FldSimple.docx"); @@ -303,7 +308,7 @@ public class TestXWPFWordExtractor extends TestCase { String text = extractor.getText(); assertTrue(text.length() > 0); assertTrue(text.contains("FldSimple.docx")); - + extractor.close(); } @@ -316,12 +321,13 @@ public class TestXWPFWordExtractor extends TestCase { XWPFWordExtractor extractor = new XWPFWordExtractor(doc); String text = extractor.getText(); assertTrue(text.length() > 0); - + extractor.close(); } - + /** * Test for basic extraction of SDT content + * * @throws IOException */ public void testSimpleControlContent() throws IOException { @@ -345,19 +351,19 @@ public class TestXWPFWordExtractor extends TestCase { XWPFWordExtractor ex = new XWPFWordExtractor(doc); String s = ex.getText().toLowerCase(); int hits = 0; - - for (String targ : targs){ + + for (String targ : targs) { boolean hit = false; - if (s.indexOf(targ) > -1){ + if (s.indexOf(targ) > -1) { hit = true; hits++; } - assertEquals("controlled content loading-"+targ, true, hit); + assertEquals("controlled content loading-" + targ, true, hit); } assertEquals("controlled content loading hit count", targs.length, hits); ex.close(); - - + + doc = XWPFTestDataSamples.openSampleDocument("Bug54771a.docx"); targs = new String[]{ "bb", @@ -366,48 +372,50 @@ public class TestXWPFWordExtractor extends TestCase { }; ex = new XWPFWordExtractor(doc); s = ex.getText().toLowerCase(); - + //At one point in development there were three copies of the text. //This ensures that there is only one copy. - for (String targ : targs){ + for (String targ : targs) { Matcher m = Pattern.compile(targ).matcher(s); int hit = 0; while (m.find()) { hit++; } - assertEquals("controlled content loading-"+targ, 1, hit); + assertEquals("controlled content loading-" + targ, 1, hit); } //"test\n" appears twice: once as the "title" and once in the text. //This also happens when you save this document as text from MSWord. Matcher m = Pattern.compile("test\n").matcher(s); int hit = 0; - while (m.find()){ + while (m.find()) { hit++; } assertEquals("test", 2, hit); ex.close(); } - /** No Header or Footer in document */ + /** + * No Header or Footer in document + */ public void testBug55733() throws Exception { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("55733.docx"); - XWPFWordExtractor extractor = new XWPFWordExtractor(doc); + XWPFWordExtractor extractor = new XWPFWordExtractor(doc); // Check it gives text without error extractor.getText(); extractor.close(); } - - public void testCheckboxes() throws IOException { + + public void testCheckboxes() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("checkboxes.docx"); System.out.println(doc); XWPFWordExtractor extractor = new XWPFWordExtractor(doc); - + assertEquals("This is a small test for checkboxes \nunchecked: |_| \n" + - "Or checked: |X|\n\n\n\n\n" + - "Test a checkbox within a textbox: |_| -> |X|\n\n\n" + - "In Table:\n|_|\t|X|\n\n\n" + - "In Sequence:\n|X||_||X|\n", extractor.getText()); + "Or checked: |X|\n\n\n\n\n" + + "Test a checkbox within a textbox: |_| -> |X|\n\n\n" + + "In Table:\n|_|\t|X|\n\n\n" + + "In Sequence:\n|X||_||X|\n", extractor.getText()); extractor.close(); } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFDecorators.java b/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFDecorators.java index 3df111bfa..aa1167dd0 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFDecorators.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFDecorators.java @@ -17,86 +17,85 @@ package org.apache.poi.xwpf.model; -import java.io.IOException; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun; import org.apache.poi.xwpf.usermodel.XWPFParagraph; /** - * Tests for the various XWPF decorators - */ -public class TestXWPFDecorators extends TestCase { - private XWPFDocument simple; - private XWPFDocument hyperlink; - private XWPFDocument comments; - - protected void setUp() throws IOException { - simple = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx"); - hyperlink = XWPFTestDataSamples.openSampleDocument("TestDocument.docx"); - comments = XWPFTestDataSamples.openSampleDocument("WordWithAttachments.docx"); - } - - @SuppressWarnings("deprecation") - public void testHyperlink() { - XWPFParagraph ps; - XWPFParagraph ph; - assertEquals(7, simple.getParagraphs().size()); - assertEquals(5, hyperlink.getParagraphs().size()); - - // Simple text - ps = simple.getParagraphs().get(0); - assertEquals("I am a test document", ps.getParagraphText()); - assertEquals(1, ps.getRuns().size()); - - ph = hyperlink.getParagraphs().get(4); - assertEquals("We have a hyperlink here, and another.", ph.getParagraphText()); - assertEquals(3, ph.getRuns().size()); - - - // The proper way to do hyperlinks(!) - assertFalse(ps.getRuns().get(0) instanceof XWPFHyperlinkRun); - assertFalse(ph.getRuns().get(0) instanceof XWPFHyperlinkRun); - assertTrue(ph.getRuns().get(1) instanceof XWPFHyperlinkRun); - assertFalse(ph.getRuns().get(2) instanceof XWPFHyperlinkRun); - - XWPFHyperlinkRun link = (XWPFHyperlinkRun)ph.getRuns().get(1); - assertEquals("http://poi.apache.org/", link.getHyperlink(hyperlink).getURL()); - - - // Test the old style decorator - // You probably don't want to still be using it... - assertEquals( - "I am a test document", - (new XWPFHyperlinkDecorator(ps, null, false)).getText() - ); - assertEquals( - "I am a test document", - (new XWPFHyperlinkDecorator(ps, null, true)).getText() - ); - - assertEquals( - "We have a hyperlink here, and another.hyperlink", - (new XWPFHyperlinkDecorator(ph, null, false)).getText() - ); - assertEquals( - "We have a hyperlink here, and another.hyperlink ", - (new XWPFHyperlinkDecorator(ph, null, true)).getText() - ); - } - - public void testComments() { - int numComments = 0; - for(XWPFParagraph p : comments.getParagraphs()) { - XWPFCommentsDecorator d = new XWPFCommentsDecorator(p, null); - if(d.getCommentText().length() > 0) { - numComments++; - assertEquals("\tComment by", d.getCommentText().substring(0, 11)); - } - } - assertEquals(3, numComments); - } -} + * Tests for the various XWPF decorators + */ +public class TestXWPFDecorators extends TestCase { + private XWPFDocument simple; + private XWPFDocument hyperlink; + private XWPFDocument comments; + + protected void setUp() throws IOException { + simple = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx"); + hyperlink = XWPFTestDataSamples.openSampleDocument("TestDocument.docx"); + comments = XWPFTestDataSamples.openSampleDocument("WordWithAttachments.docx"); + } + + @SuppressWarnings("deprecation") + public void testHyperlink() { + XWPFParagraph ps; + XWPFParagraph ph; + assertEquals(7, simple.getParagraphs().size()); + assertEquals(5, hyperlink.getParagraphs().size()); + + // Simple text + ps = simple.getParagraphs().get(0); + assertEquals("I am a test document", ps.getParagraphText()); + assertEquals(1, ps.getRuns().size()); + + ph = hyperlink.getParagraphs().get(4); + assertEquals("We have a hyperlink here, and another.", ph.getParagraphText()); + assertEquals(3, ph.getRuns().size()); + + + // The proper way to do hyperlinks(!) + assertFalse(ps.getRuns().get(0) instanceof XWPFHyperlinkRun); + assertFalse(ph.getRuns().get(0) instanceof XWPFHyperlinkRun); + assertTrue(ph.getRuns().get(1) instanceof XWPFHyperlinkRun); + assertFalse(ph.getRuns().get(2) instanceof XWPFHyperlinkRun); + + XWPFHyperlinkRun link = (XWPFHyperlinkRun) ph.getRuns().get(1); + assertEquals("http://poi.apache.org/", link.getHyperlink(hyperlink).getURL()); + + + // Test the old style decorator + // You probably don't want to still be using it... + assertEquals( + "I am a test document", + (new XWPFHyperlinkDecorator(ps, null, false)).getText() + ); + assertEquals( + "I am a test document", + (new XWPFHyperlinkDecorator(ps, null, true)).getText() + ); + + assertEquals( + "We have a hyperlink here, and another.hyperlink", + (new XWPFHyperlinkDecorator(ph, null, false)).getText() + ); + assertEquals( + "We have a hyperlink here, and another.hyperlink ", + (new XWPFHyperlinkDecorator(ph, null, true)).getText() + ); + } + + public void testComments() { + int numComments = 0; + for (XWPFParagraph p : comments.getParagraphs()) { + XWPFCommentsDecorator d = new XWPFCommentsDecorator(p, null); + if (d.getCommentText().length() > 0) { + numComments++; + assertEquals("\tComment by", d.getCommentText().substring(0, 11)); + } + } + assertEquals(3, numComments); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFHeaderFooterPolicy.java b/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFHeaderFooterPolicy.java index 7d70866e8..d461265d4 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFHeaderFooterPolicy.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/model/TestXWPFHeaderFooterPolicy.java @@ -20,7 +20,6 @@ package org.apache.poi.xwpf.model; import java.io.IOException; import junit.framework.TestCase; - import org.apache.poi.xwpf.XWPFTestDataSamples; import org.apache.poi.xwpf.usermodel.XWPFDocument; @@ -28,130 +27,130 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument; * Tests for XWPF Header Footer Stuff */ public class TestXWPFHeaderFooterPolicy extends TestCase { - private XWPFDocument noHeader; - private XWPFDocument header; - private XWPFDocument headerFooter; - private XWPFDocument footer; - private XWPFDocument oddEven; - private XWPFDocument diffFirst; + private XWPFDocument noHeader; + private XWPFDocument header; + private XWPFDocument headerFooter; + private XWPFDocument footer; + private XWPFDocument oddEven; + private XWPFDocument diffFirst; - protected void setUp() throws IOException { + protected void setUp() throws IOException { - noHeader = XWPFTestDataSamples.openSampleDocument("NoHeadFoot.docx"); - header = XWPFTestDataSamples.openSampleDocument("ThreeColHead.docx"); - headerFooter = XWPFTestDataSamples.openSampleDocument("SimpleHeadThreeColFoot.docx"); - footer = XWPFTestDataSamples.openSampleDocument("FancyFoot.docx"); - oddEven = XWPFTestDataSamples.openSampleDocument("PageSpecificHeadFoot.docx"); - diffFirst = XWPFTestDataSamples.openSampleDocument("DiffFirstPageHeadFoot.docx"); - } + noHeader = XWPFTestDataSamples.openSampleDocument("NoHeadFoot.docx"); + header = XWPFTestDataSamples.openSampleDocument("ThreeColHead.docx"); + headerFooter = XWPFTestDataSamples.openSampleDocument("SimpleHeadThreeColFoot.docx"); + footer = XWPFTestDataSamples.openSampleDocument("FancyFoot.docx"); + oddEven = XWPFTestDataSamples.openSampleDocument("PageSpecificHeadFoot.docx"); + diffFirst = XWPFTestDataSamples.openSampleDocument("DiffFirstPageHeadFoot.docx"); + } - public void testPolicy() { - XWPFHeaderFooterPolicy policy; + public void testPolicy() { + XWPFHeaderFooterPolicy policy; - policy = noHeader.getHeaderFooterPolicy(); - assertNull(policy.getDefaultHeader()); - assertNull(policy.getDefaultFooter()); + policy = noHeader.getHeaderFooterPolicy(); + assertNull(policy.getDefaultHeader()); + assertNull(policy.getDefaultFooter()); - assertNull(policy.getHeader(1)); - assertNull(policy.getHeader(2)); - assertNull(policy.getHeader(3)); - assertNull(policy.getFooter(1)); - assertNull(policy.getFooter(2)); - assertNull(policy.getFooter(3)); + assertNull(policy.getHeader(1)); + assertNull(policy.getHeader(2)); + assertNull(policy.getHeader(3)); + assertNull(policy.getFooter(1)); + assertNull(policy.getFooter(2)); + assertNull(policy.getFooter(3)); - policy = header.getHeaderFooterPolicy(); - assertNotNull(policy.getDefaultHeader()); - assertNull(policy.getDefaultFooter()); + policy = header.getHeaderFooterPolicy(); + assertNotNull(policy.getDefaultHeader()); + assertNull(policy.getDefaultFooter()); - assertEquals(policy.getDefaultHeader(), policy.getHeader(1)); - assertEquals(policy.getDefaultHeader(), policy.getHeader(2)); - assertEquals(policy.getDefaultHeader(), policy.getHeader(3)); - assertNull(policy.getFooter(1)); - assertNull(policy.getFooter(2)); - assertNull(policy.getFooter(3)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(1)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(2)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(3)); + assertNull(policy.getFooter(1)); + assertNull(policy.getFooter(2)); + assertNull(policy.getFooter(3)); - policy = footer.getHeaderFooterPolicy(); - assertNull(policy.getDefaultHeader()); - assertNotNull(policy.getDefaultFooter()); + policy = footer.getHeaderFooterPolicy(); + assertNull(policy.getDefaultHeader()); + assertNotNull(policy.getDefaultFooter()); - assertNull(policy.getHeader(1)); - assertNull(policy.getHeader(2)); - assertNull(policy.getHeader(3)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(1)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(2)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(3)); + assertNull(policy.getHeader(1)); + assertNull(policy.getHeader(2)); + assertNull(policy.getHeader(3)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(1)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(2)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(3)); - policy = headerFooter.getHeaderFooterPolicy(); - assertNotNull(policy.getDefaultHeader()); - assertNotNull(policy.getDefaultFooter()); + policy = headerFooter.getHeaderFooterPolicy(); + assertNotNull(policy.getDefaultHeader()); + assertNotNull(policy.getDefaultFooter()); - assertEquals(policy.getDefaultHeader(), policy.getHeader(1)); - assertEquals(policy.getDefaultHeader(), policy.getHeader(2)); - assertEquals(policy.getDefaultHeader(), policy.getHeader(3)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(1)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(2)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(3)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(1)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(2)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(3)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(1)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(2)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(3)); - policy = oddEven.getHeaderFooterPolicy(); - assertNotNull(policy.getDefaultHeader()); - assertNotNull(policy.getDefaultFooter()); - assertNotNull(policy.getEvenPageHeader()); - assertNotNull(policy.getEvenPageFooter()); + policy = oddEven.getHeaderFooterPolicy(); + assertNotNull(policy.getDefaultHeader()); + assertNotNull(policy.getDefaultFooter()); + assertNotNull(policy.getEvenPageHeader()); + assertNotNull(policy.getEvenPageFooter()); - assertEquals(policy.getDefaultHeader(), policy.getHeader(1)); - assertEquals(policy.getEvenPageHeader(), policy.getHeader(2)); - assertEquals(policy.getDefaultHeader(), policy.getHeader(3)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(1)); - assertEquals(policy.getEvenPageFooter(), policy.getFooter(2)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(3)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(1)); + assertEquals(policy.getEvenPageHeader(), policy.getHeader(2)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(3)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(1)); + assertEquals(policy.getEvenPageFooter(), policy.getFooter(2)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(3)); - policy = diffFirst.getHeaderFooterPolicy(); - assertNotNull(policy.getDefaultHeader()); - assertNotNull(policy.getDefaultFooter()); - assertNotNull(policy.getFirstPageHeader()); - assertNotNull(policy.getFirstPageFooter()); - assertNull(policy.getEvenPageHeader()); - assertNull(policy.getEvenPageFooter()); + policy = diffFirst.getHeaderFooterPolicy(); + assertNotNull(policy.getDefaultHeader()); + assertNotNull(policy.getDefaultFooter()); + assertNotNull(policy.getFirstPageHeader()); + assertNotNull(policy.getFirstPageFooter()); + assertNull(policy.getEvenPageHeader()); + assertNull(policy.getEvenPageFooter()); - assertEquals(policy.getFirstPageHeader(), policy.getHeader(1)); - assertEquals(policy.getDefaultHeader(), policy.getHeader(2)); - assertEquals(policy.getDefaultHeader(), policy.getHeader(3)); - assertEquals(policy.getFirstPageFooter(), policy.getFooter(1)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(2)); - assertEquals(policy.getDefaultFooter(), policy.getFooter(3)); - } + assertEquals(policy.getFirstPageHeader(), policy.getHeader(1)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(2)); + assertEquals(policy.getDefaultHeader(), policy.getHeader(3)); + assertEquals(policy.getFirstPageFooter(), policy.getFooter(1)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(2)); + assertEquals(policy.getDefaultFooter(), policy.getFooter(3)); + } - public void testContents() { - XWPFHeaderFooterPolicy policy; + public void testContents() { + XWPFHeaderFooterPolicy policy; - // Test a few simple bits off a simple header - policy = diffFirst.getHeaderFooterPolicy(); + // Test a few simple bits off a simple header + policy = diffFirst.getHeaderFooterPolicy(); - assertEquals( - "I am the header on the first page, and I" + '\u2019' + "m nice and simple\n", - policy.getFirstPageHeader().getText() - ); - assertEquals( - "First header column!\tMid header\tRight header!\n", - policy.getDefaultHeader().getText() - ); + assertEquals( + "I am the header on the first page, and I" + '\u2019' + "m nice and simple\n", + policy.getFirstPageHeader().getText() + ); + assertEquals( + "First header column!\tMid header\tRight header!\n", + policy.getDefaultHeader().getText() + ); - // And a few bits off a more complex header - policy = oddEven.getHeaderFooterPolicy(); + // And a few bits off a more complex header + policy = oddEven.getHeaderFooterPolicy(); - assertEquals( - "[ODD Page Header text]\n\n", - policy.getDefaultHeader().getText() - ); - assertEquals( - "[This is an Even Page, with a Header]\n\n", - policy.getEvenPageHeader().getText() - ); - } + assertEquals( + "[ODD Page Header text]\n\n", + policy.getDefaultHeader().getText() + ); + assertEquals( + "[This is an Even Page, with a Header]\n\n", + policy.getEvenPageHeader().getText() + ); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestChangeTracking.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestChangeTracking.java index d3e4758e1..0a309a830 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestChangeTracking.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestChangeTracking.java @@ -44,7 +44,7 @@ public class TestChangeTracking { assertFalse(document.isTrackRevisions()); document.setTrackRevisions(true); - + assertTrue(document.isTrackRevisions()); } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFBugs.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFBugs.java index bded4e48c..78df19c00 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFBugs.java @@ -16,10 +16,12 @@ ==================================================================== */ package org.apache.poi.xwpf.usermodel; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import java.io.IOException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.xwpf.XWPFTestDataSamples; import org.apache.poi.xwpf.usermodel.XWPFRun.FontCharRange; import org.junit.Test; @@ -28,14 +30,14 @@ public class TestXWPFBugs { @Test public void bug55802() throws Exception { String blabla = - "Bir, iki, \u00fc\u00e7, d\u00f6rt, be\u015f,\n"+ - "\nalt\u0131, yedi, sekiz, dokuz, on.\n"+ - "\nK\u0131rm\u0131z\u0131 don,\n"+ - "\ngel bizim bah\u00e7eye kon,\n"+ - "\nsar\u0131 limon"; + "Bir, iki, \u00fc\u00e7, d\u00f6rt, be\u015f,\n" + + "\nalt\u0131, yedi, sekiz, dokuz, on.\n" + + "\nK\u0131rm\u0131z\u0131 don,\n" + + "\ngel bizim bah\u00e7eye kon,\n" + + "\nsar\u0131 limon"; XWPFDocument doc = new XWPFDocument(); XWPFRun run = doc.createParagraph().createRun(); - + for (String str : blabla.split("\n")) { run.setText(str); run.addBreak(); @@ -51,30 +53,52 @@ public class TestXWPFBugs { assertEquals(run.getFontFamily(FontCharRange.hAnsi), "Arial"); } - + @Test public void bug57312_NullPointException() throws IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("57312.docx"); assertNotNull(doc); - - for( IBodyElement bodyElement : doc.getBodyElements()){ + + for (IBodyElement bodyElement : doc.getBodyElements()) { BodyElementType elementType = bodyElement.getElementType(); - - if(elementType == BodyElementType.PARAGRAPH) { + + if (elementType == BodyElementType.PARAGRAPH) { XWPFParagraph paragraph = (XWPFParagraph) bodyElement; - - for (IRunElement iRunElem : paragraph.getIRuns()){ - - if (iRunElem instanceof XWPFRun){ + + for (IRunElement iRunElem : paragraph.getIRuns()) { + + if (iRunElem instanceof XWPFRun) { XWPFRun runElement = (XWPFRun) iRunElem; - + UnderlinePatterns underline = runElement.getUnderline(); assertNotNull(underline); - + //System.out.println("Found: " + underline + ": " + runElement.getText(0)); } } - } + } + } + } + + + @Test + public void test56392() throws IOException, OpenXML4JException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("56392.docx"); + assertNotNull(doc); + } + + /** + * Removing a run needs to remove it from both Runs and IRuns + */ + @Test + public void test57829() throws Exception { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); + assertNotNull(doc); + assertEquals(3, doc.getParagraphs().size()); + + for (XWPFParagraph paragraph : doc.getParagraphs()) { + paragraph.removeRun(0); + assertNotNull(paragraph.getText()); } } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java index 7621404b8..f46fd716b 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFDocument.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.List; import junit.framework.TestCase; - import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.POIXMLProperties; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; @@ -39,106 +38,105 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; public final class TestXWPFDocument extends TestCase { - public void testContainsMainContentType() throws Exception { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); - OPCPackage pack = doc.getPackage(); + public void testContainsMainContentType() throws Exception { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); + OPCPackage pack = doc.getPackage(); - boolean found = false; - for(PackagePart part : pack.getParts()) { - if(part.getContentType().equals(XWPFRelation.DOCUMENT.getContentType())) { - found = true; - } - if (false) { - // successful tests should be silent - System.out.println(part); - } - } - assertTrue(found); - } + boolean found = false; + for (PackagePart part : pack.getParts()) { + if (part.getContentType().equals(XWPFRelation.DOCUMENT.getContentType())) { + found = true; + } + if (false) { + // successful tests should be silent + System.out.println(part); + } + } + assertTrue(found); + } - public void testOpen() throws Exception { - XWPFDocument xml; + public void testOpen() throws Exception { + XWPFDocument xml; - // Simple file - xml = XWPFTestDataSamples.openSampleDocument("sample.docx"); - // Check it has key parts - assertNotNull(xml.getDocument()); - assertNotNull(xml.getDocument().getBody()); - assertNotNull(xml.getStyle()); + // Simple file + xml = XWPFTestDataSamples.openSampleDocument("sample.docx"); + // Check it has key parts + assertNotNull(xml.getDocument()); + assertNotNull(xml.getDocument().getBody()); + assertNotNull(xml.getStyle()); - // Complex file - xml = XWPFTestDataSamples.openSampleDocument("IllustrativeCases.docx"); - assertNotNull(xml.getDocument()); - assertNotNull(xml.getDocument().getBody()); - assertNotNull(xml.getStyle()); - } + // Complex file + xml = XWPFTestDataSamples.openSampleDocument("IllustrativeCases.docx"); + assertNotNull(xml.getDocument()); + assertNotNull(xml.getDocument().getBody()); + assertNotNull(xml.getStyle()); + } - public void testMetadataBasics() throws IOException { - XWPFDocument xml = XWPFTestDataSamples.openSampleDocument("sample.docx"); - assertNotNull(xml.getProperties().getCoreProperties()); - assertNotNull(xml.getProperties().getExtendedProperties()); + public void testMetadataBasics() throws IOException { + XWPFDocument xml = XWPFTestDataSamples.openSampleDocument("sample.docx"); + assertNotNull(xml.getProperties().getCoreProperties()); + assertNotNull(xml.getProperties().getExtendedProperties()); - assertEquals("Microsoft Office Word", xml.getProperties().getExtendedProperties().getUnderlyingProperties().getApplication()); - assertEquals(1315, xml.getProperties().getExtendedProperties().getUnderlyingProperties().getCharacters()); - assertEquals(10, xml.getProperties().getExtendedProperties().getUnderlyingProperties().getLines()); + assertEquals("Microsoft Office Word", xml.getProperties().getExtendedProperties().getUnderlyingProperties().getApplication()); + assertEquals(1315, xml.getProperties().getExtendedProperties().getUnderlyingProperties().getCharacters()); + assertEquals(10, xml.getProperties().getExtendedProperties().getUnderlyingProperties().getLines()); - assertEquals(null, xml.getProperties().getCoreProperties().getTitle()); - assertEquals(null, xml.getProperties().getCoreProperties().getUnderlyingProperties().getSubjectProperty().getValue()); - } + assertEquals(null, xml.getProperties().getCoreProperties().getTitle()); + assertEquals(null, xml.getProperties().getCoreProperties().getUnderlyingProperties().getSubjectProperty().getValue()); + } - public void testMetadataComplex() throws IOException { - XWPFDocument xml = XWPFTestDataSamples.openSampleDocument("IllustrativeCases.docx"); - assertNotNull(xml.getProperties().getCoreProperties()); - assertNotNull(xml.getProperties().getExtendedProperties()); + public void testMetadataComplex() throws IOException { + XWPFDocument xml = XWPFTestDataSamples.openSampleDocument("IllustrativeCases.docx"); + assertNotNull(xml.getProperties().getCoreProperties()); + assertNotNull(xml.getProperties().getExtendedProperties()); - assertEquals("Microsoft Office Outlook", xml.getProperties().getExtendedProperties().getUnderlyingProperties().getApplication()); - assertEquals(5184, xml.getProperties().getExtendedProperties().getUnderlyingProperties().getCharacters()); - assertEquals(0, xml.getProperties().getExtendedProperties().getUnderlyingProperties().getLines()); + assertEquals("Microsoft Office Outlook", xml.getProperties().getExtendedProperties().getUnderlyingProperties().getApplication()); + assertEquals(5184, xml.getProperties().getExtendedProperties().getUnderlyingProperties().getCharacters()); + assertEquals(0, xml.getProperties().getExtendedProperties().getUnderlyingProperties().getLines()); - assertEquals(" ", xml.getProperties().getCoreProperties().getTitle()); - assertEquals(" ", xml.getProperties().getCoreProperties().getUnderlyingProperties().getSubjectProperty().getValue()); - } + assertEquals(" ", xml.getProperties().getCoreProperties().getTitle()); + assertEquals(" ", xml.getProperties().getCoreProperties().getUnderlyingProperties().getSubjectProperty().getValue()); + } - public void testWorkbookProperties() { - XWPFDocument doc = new XWPFDocument(); - POIXMLProperties props = doc.getProperties(); - assertNotNull(props); - assertEquals("Apache POI", props.getExtendedProperties().getUnderlyingProperties().getApplication()); - } - - public void testAddParagraph() throws IOException{ - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); - assertEquals(3, doc.getParagraphs().size()); + public void testWorkbookProperties() { + XWPFDocument doc = new XWPFDocument(); + POIXMLProperties props = doc.getProperties(); + assertNotNull(props); + assertEquals("Apache POI", props.getExtendedProperties().getUnderlyingProperties().getApplication()); + } - XWPFParagraph p = doc.createParagraph(); - assertEquals(p, doc.getParagraphs().get(3)); - assertEquals(4, doc.getParagraphs().size()); - - assertEquals(3, doc.getParagraphPos(3)); - assertEquals(3, doc.getPosOfParagraph(p)); + public void testAddParagraph() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); + assertEquals(3, doc.getParagraphs().size()); - CTP ctp = p.getCTP(); - XWPFParagraph newP = doc.getParagraph(ctp); - assertSame(p, newP); - XmlCursor cursor = doc.getDocument().getBody().getPArray(0).newCursor(); - XWPFParagraph cP = doc.insertNewParagraph(cursor); - assertSame(cP, doc.getParagraphs().get(0)); - assertEquals(5, doc.getParagraphs().size()); - } + XWPFParagraph p = doc.createParagraph(); + assertEquals(p, doc.getParagraphs().get(3)); + assertEquals(4, doc.getParagraphs().size()); - public void testAddPicture() throws IOException, InvalidFormatException - { + assertEquals(3, doc.getParagraphPos(3)); + assertEquals(3, doc.getPosOfParagraph(p)); + + CTP ctp = p.getCTP(); + XWPFParagraph newP = doc.getParagraph(ctp); + assertSame(p, newP); + XmlCursor cursor = doc.getDocument().getBody().getPArray(0).newCursor(); + XWPFParagraph cP = doc.insertNewParagraph(cursor); + assertSame(cP, doc.getParagraphs().get(0)); + assertEquals(5, doc.getParagraphs().size()); + } + + public void testAddPicture() throws IOException, InvalidFormatException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); byte[] jpeg = XWPFTestDataSamples.getImage("nature1.jpg"); - String relationId = doc.addPictureData(jpeg,XWPFDocument.PICTURE_TYPE_JPEG); - + String relationId = doc.addPictureData(jpeg, XWPFDocument.PICTURE_TYPE_JPEG); + byte[] newJpeg = ((XWPFPictureData) doc.getRelationById(relationId)).getData(); - assertEquals(newJpeg.length,jpeg.length); - for (int i = 0 ; i < jpeg.length ; i++) - { - assertEquals(newJpeg[i],jpeg[i]); + assertEquals(newJpeg.length, jpeg.length); + for (int i = 0; i < jpeg.length; i++) { + assertEquals(newJpeg[i], jpeg[i]); } } + public void testAllPictureFormats() throws IOException, InvalidFormatException { XWPFDocument doc = new XWPFDocument(); @@ -161,184 +159,200 @@ public final class TestXWPFDocument extends TestCase { } - public void testRemoveBodyElement() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); - assertEquals(3, doc.getParagraphs().size()); - assertEquals(3, doc.getBodyElements().size()); - - XWPFParagraph p1 = doc.getParagraphs().get(0); - XWPFParagraph p2 = doc.getParagraphs().get(1); - XWPFParagraph p3 = doc.getParagraphs().get(2); - - assertEquals(p1, doc.getBodyElements().get(0)); - assertEquals(p1, doc.getParagraphs().get(0)); - assertEquals(p2, doc.getBodyElements().get(1)); - assertEquals(p2, doc.getParagraphs().get(1)); - assertEquals(p3, doc.getBodyElements().get(2)); - assertEquals(p3, doc.getParagraphs().get(2)); - - // Add another - XWPFParagraph p4 = doc.createParagraph(); - - assertEquals(4, doc.getParagraphs().size()); - assertEquals(4, doc.getBodyElements().size()); - assertEquals(p1, doc.getBodyElements().get(0)); - assertEquals(p1, doc.getParagraphs().get(0)); - assertEquals(p2, doc.getBodyElements().get(1)); - assertEquals(p2, doc.getParagraphs().get(1)); - assertEquals(p3, doc.getBodyElements().get(2)); - assertEquals(p3, doc.getParagraphs().get(2)); - assertEquals(p4, doc.getBodyElements().get(3)); - assertEquals(p4, doc.getParagraphs().get(3)); - - // Remove the 2nd - assertEquals(true, doc.removeBodyElement(1)); - assertEquals(3, doc.getParagraphs().size()); - assertEquals(3, doc.getBodyElements().size()); - - assertEquals(p1, doc.getBodyElements().get(0)); - assertEquals(p1, doc.getParagraphs().get(0)); - assertEquals(p3, doc.getBodyElements().get(1)); - assertEquals(p3, doc.getParagraphs().get(1)); - assertEquals(p4, doc.getBodyElements().get(2)); - assertEquals(p4, doc.getParagraphs().get(2)); - - // Remove the 1st - assertEquals(true, doc.removeBodyElement(0)); - assertEquals(2, doc.getParagraphs().size()); - assertEquals(2, doc.getBodyElements().size()); - - assertEquals(p3, doc.getBodyElements().get(0)); - assertEquals(p3, doc.getParagraphs().get(0)); - assertEquals(p4, doc.getBodyElements().get(1)); - assertEquals(p4, doc.getParagraphs().get(1)); - - // Remove the last - assertEquals(true, doc.removeBodyElement(1)); - assertEquals(1, doc.getParagraphs().size()); - assertEquals(1, doc.getBodyElements().size()); - - assertEquals(p3, doc.getBodyElements().get(0)); - assertEquals(p3, doc.getParagraphs().get(0)); - } - - public void testRegisterPackagePictureData() throws IOException, InvalidFormatException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_1.docx"); - - /* manually assemble a new image package part*/ - OPCPackage opcPckg = doc.getPackage(); - XWPFRelation jpgRelation = XWPFRelation.IMAGE_JPEG; - PackagePartName partName = PackagingURIHelper.createPartName(jpgRelation.getDefaultFileName().replace('#', '2')); + public void testRemoveBodyElement() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); + assertEquals(3, doc.getParagraphs().size()); + assertEquals(3, doc.getBodyElements().size()); + + XWPFParagraph p1 = doc.getParagraphs().get(0); + XWPFParagraph p2 = doc.getParagraphs().get(1); + XWPFParagraph p3 = doc.getParagraphs().get(2); + + assertEquals(p1, doc.getBodyElements().get(0)); + assertEquals(p1, doc.getParagraphs().get(0)); + assertEquals(p2, doc.getBodyElements().get(1)); + assertEquals(p2, doc.getParagraphs().get(1)); + assertEquals(p3, doc.getBodyElements().get(2)); + assertEquals(p3, doc.getParagraphs().get(2)); + + // Add another + XWPFParagraph p4 = doc.createParagraph(); + + assertEquals(4, doc.getParagraphs().size()); + assertEquals(4, doc.getBodyElements().size()); + assertEquals(p1, doc.getBodyElements().get(0)); + assertEquals(p1, doc.getParagraphs().get(0)); + assertEquals(p2, doc.getBodyElements().get(1)); + assertEquals(p2, doc.getParagraphs().get(1)); + assertEquals(p3, doc.getBodyElements().get(2)); + assertEquals(p3, doc.getParagraphs().get(2)); + assertEquals(p4, doc.getBodyElements().get(3)); + assertEquals(p4, doc.getParagraphs().get(3)); + + // Remove the 2nd + assertEquals(true, doc.removeBodyElement(1)); + assertEquals(3, doc.getParagraphs().size()); + assertEquals(3, doc.getBodyElements().size()); + + assertEquals(p1, doc.getBodyElements().get(0)); + assertEquals(p1, doc.getParagraphs().get(0)); + assertEquals(p3, doc.getBodyElements().get(1)); + assertEquals(p3, doc.getParagraphs().get(1)); + assertEquals(p4, doc.getBodyElements().get(2)); + assertEquals(p4, doc.getParagraphs().get(2)); + + // Remove the 1st + assertEquals(true, doc.removeBodyElement(0)); + assertEquals(2, doc.getParagraphs().size()); + assertEquals(2, doc.getBodyElements().size()); + + assertEquals(p3, doc.getBodyElements().get(0)); + assertEquals(p3, doc.getParagraphs().get(0)); + assertEquals(p4, doc.getBodyElements().get(1)); + assertEquals(p4, doc.getParagraphs().get(1)); + + // Remove the last + assertEquals(true, doc.removeBodyElement(1)); + assertEquals(1, doc.getParagraphs().size()); + assertEquals(1, doc.getBodyElements().size()); + + assertEquals(p3, doc.getBodyElements().get(0)); + assertEquals(p3, doc.getParagraphs().get(0)); + } + + public void testRegisterPackagePictureData() throws IOException, InvalidFormatException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_1.docx"); + + /* manually assemble a new image package part*/ + OPCPackage opcPckg = doc.getPackage(); + XWPFRelation jpgRelation = XWPFRelation.IMAGE_JPEG; + PackagePartName partName = PackagingURIHelper.createPartName(jpgRelation.getDefaultFileName().replace('#', '2')); PackagePart newImagePart = opcPckg.createPart(partName, jpgRelation.getContentType()); byte[] nature1 = XWPFTestDataSamples.getImage("abstract4.jpg"); OutputStream os = newImagePart.getOutputStream(); os.write(nature1); - os.close(); - XWPFHeader xwpfHeader = doc.getHeaderArray(0); - PackageRelationship relationship = xwpfHeader.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, jpgRelation.getRelation()); - XWPFPictureData newPicData = new XWPFPictureData(newImagePart,relationship); - /* new part is now ready to rumble */ - - assertFalse(xwpfHeader.getAllPictures().contains(newPicData)); - assertFalse(doc.getAllPictures().contains(newPicData)); - assertFalse(doc.getAllPackagePictures().contains(newPicData)); + os.close(); + XWPFHeader xwpfHeader = doc.getHeaderArray(0); + PackageRelationship relationship = xwpfHeader.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, jpgRelation.getRelation()); + XWPFPictureData newPicData = new XWPFPictureData(newImagePart, relationship); + /* new part is now ready to rumble */ - doc.registerPackagePictureData(newPicData); - - assertFalse(xwpfHeader.getAllPictures().contains(newPicData)); - assertFalse(doc.getAllPictures().contains(newPicData)); - assertTrue(doc.getAllPackagePictures().contains(newPicData)); - - doc.getPackage().revert(); - } + assertFalse(xwpfHeader.getAllPictures().contains(newPicData)); + assertFalse(doc.getAllPictures().contains(newPicData)); + assertFalse(doc.getAllPackagePictures().contains(newPicData)); - public void testFindPackagePictureData() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_1.docx"); - byte[] nature1 = XWPFTestDataSamples.getImage("nature1.gif"); - XWPFPictureData part = doc.findPackagePictureData(nature1, Document.PICTURE_TYPE_GIF); - assertNotNull(part); - assertTrue(doc.getAllPictures().contains(part)); - assertTrue(doc.getAllPackagePictures().contains(part)); - doc.getPackage().revert(); - } - - public void testGetAllPictures() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_3.docx"); - List allPictures = doc.getAllPictures(); - List allPackagePictures = doc.getAllPackagePictures(); - - assertNotNull(allPictures); - assertEquals(3,allPictures.size()); - for (XWPFPictureData xwpfPictureData : allPictures) { - assertTrue(allPackagePictures.contains(xwpfPictureData)); + doc.registerPackagePictureData(newPicData); + + assertFalse(xwpfHeader.getAllPictures().contains(newPicData)); + assertFalse(doc.getAllPictures().contains(newPicData)); + assertTrue(doc.getAllPackagePictures().contains(newPicData)); + + doc.getPackage().revert(); + } + + public void testFindPackagePictureData() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_1.docx"); + byte[] nature1 = XWPFTestDataSamples.getImage("nature1.gif"); + XWPFPictureData part = doc.findPackagePictureData(nature1, Document.PICTURE_TYPE_GIF); + assertNotNull(part); + assertTrue(doc.getAllPictures().contains(part)); + assertTrue(doc.getAllPackagePictures().contains(part)); + doc.getPackage().revert(); + } + + public void testGetAllPictures() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_3.docx"); + List allPictures = doc.getAllPictures(); + List allPackagePictures = doc.getAllPackagePictures(); + + assertNotNull(allPictures); + assertEquals(3, allPictures.size()); + for (XWPFPictureData xwpfPictureData : allPictures) { + assertTrue(allPackagePictures.contains(xwpfPictureData)); } - try { + try { allPictures.add(allPictures.get(0)); fail("This list must be unmodifiable!"); } catch (UnsupportedOperationException e) { // all ok } - - doc.getPackage().revert(); - } - public void testGetAllPackagePictures() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_3.docx"); - List allPackagePictures = doc.getAllPackagePictures(); - - assertNotNull(allPackagePictures); - assertEquals(5,allPackagePictures.size()); + doc.getPackage().revert(); + } - try { - allPackagePictures.add(allPackagePictures.get(0)); - fail("This list must be unmodifiable!"); - } catch (UnsupportedOperationException e) { - // all ok - } - - doc.getPackage().revert(); - } - - public void testPictureHandlingSimpleFile() throws IOException, InvalidFormatException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_1.docx"); - assertEquals(1,doc.getAllPackagePictures().size()); - byte[] newPic = XWPFTestDataSamples.getImage("abstract4.jpg"); - String id1 = doc.addPictureData(newPic, Document.PICTURE_TYPE_JPEG); - assertEquals(2,doc.getAllPackagePictures().size()); - /* copy data, to avoid instance-equality */ - byte[] newPicCopy = Arrays.copyOf(newPic, newPic.length); - String id2 = doc.addPictureData(newPicCopy, Document.PICTURE_TYPE_JPEG); - assertEquals(id1,id2); - doc.getPackage().revert(); - } - - public void testPictureHandlingHeaderDocumentImages() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_2.docx"); - assertEquals(1,doc.getAllPictures().size()); - assertEquals(1,doc.getAllPackagePictures().size()); - assertEquals(1,doc.getHeaderArray(0).getAllPictures().size()); - doc.getPackage().revert(); - } - - public void testPictureHandlingComplex() throws IOException, InvalidFormatException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_3.docx"); - XWPFHeader xwpfHeader = doc.getHeaderArray(0); + public void testGetAllPackagePictures() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_3.docx"); + List allPackagePictures = doc.getAllPackagePictures(); - assertEquals(3,doc.getAllPictures().size()); - assertEquals(3,xwpfHeader.getAllPictures().size()); - assertEquals(5,doc.getAllPackagePictures().size()); - - byte[] nature1 = XWPFTestDataSamples.getImage("nature1.jpg"); - String id = doc.addPictureData(nature1, Document.PICTURE_TYPE_JPEG); - POIXMLDocumentPart part1 = xwpfHeader.getRelationById("rId1"); - XWPFPictureData part2 = (XWPFPictureData) doc.getRelationById(id); - assertSame(part1,part2); - - doc.getPackage().revert(); - } + assertNotNull(allPackagePictures); + assertEquals(5, allPackagePictures.size()); - public void testSettings(){ + try { + allPackagePictures.add(allPackagePictures.get(0)); + fail("This list must be unmodifiable!"); + } catch (UnsupportedOperationException e) { + // all ok + } + + doc.getPackage().revert(); + } + + public void testPictureHandlingSimpleFile() throws IOException, InvalidFormatException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_1.docx"); + assertEquals(1, doc.getAllPackagePictures().size()); + byte[] newPic = XWPFTestDataSamples.getImage("abstract4.jpg"); + String id1 = doc.addPictureData(newPic, Document.PICTURE_TYPE_JPEG); + assertEquals(2, doc.getAllPackagePictures().size()); + /* copy data, to avoid instance-equality */ + byte[] newPicCopy = Arrays.copyOf(newPic, newPic.length); + String id2 = doc.addPictureData(newPicCopy, Document.PICTURE_TYPE_JPEG); + assertEquals(id1, id2); + doc.getPackage().revert(); + } + + public void testPictureHandlingHeaderDocumentImages() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_2.docx"); + assertEquals(1, doc.getAllPictures().size()); + assertEquals(1, doc.getAllPackagePictures().size()); + assertEquals(1, doc.getHeaderArray(0).getAllPictures().size()); + doc.getPackage().revert(); + } + + public void testPictureHandlingComplex() throws IOException, InvalidFormatException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("issue_51265_3.docx"); + XWPFHeader xwpfHeader = doc.getHeaderArray(0); + + assertEquals(3, doc.getAllPictures().size()); + assertEquals(3, xwpfHeader.getAllPictures().size()); + assertEquals(5, doc.getAllPackagePictures().size()); + + byte[] nature1 = XWPFTestDataSamples.getImage("nature1.jpg"); + String id = doc.addPictureData(nature1, Document.PICTURE_TYPE_JPEG); + POIXMLDocumentPart part1 = xwpfHeader.getRelationById("rId1"); + XWPFPictureData part2 = (XWPFPictureData) doc.getRelationById(id); + assertSame(part1, part2); + + doc.getPackage().revert(); + } + + public void testZeroLengthLibreOfficeDocumentWithWaterMarkHeader() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("zero-length.docx"); + POIXMLProperties properties = doc.getProperties(); + + assertNotNull(properties.getCoreProperties()); + + XWPFHeader headerArray = doc.getHeaderArray(0); + assertEquals(1, headerArray.getAllPictures().size()); + assertEquals("image1.png", headerArray.pictures.get(0).getFileName()); + assertEquals("", headerArray.getText()); + + POIXMLProperties.ExtendedProperties extendedProperties = properties.getExtendedProperties(); + assertNotNull(extendedProperties); + assertEquals(0, extendedProperties.getUnderlyingProperties().getCharacters()); + } + + public void testSettings() { XWPFSettings settings = new XWPFSettings(); settings.setZoomPercent(50); assertEquals(50, settings.getZoomPercent()); diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFFootnotes.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFFootnotes.java index fb97bf594..0915de0fe 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFFootnotes.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFFootnotes.java @@ -19,52 +19,50 @@ package org.apache.poi.xwpf.usermodel; import java.io.IOException; import java.math.BigInteger; -import java.util.List; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; - -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFtnEdn; - -public class TestXWPFFootnotes extends TestCase { - - public void testAddFootnotesToDocument() throws IOException{ - XWPFDocument docOut = new XWPFDocument(); - - BigInteger noteId = BigInteger.valueOf(1); - - XWPFFootnotes footnotes = docOut.createFootnotes(); - CTFtnEdn ctNote = CTFtnEdn.Factory.newInstance(); - ctNote.setId(noteId); - ctNote.setType(STFtnEdn.NORMAL); - footnotes.addFootnote(ctNote); - - XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut); - - XWPFFootnote note = docIn.getFootnoteByID(noteId.intValue()); - assertEquals(note.getCTFtnEdn().getType(), STFtnEdn.NORMAL); - } - - /** - * Bug 55066 - avoid double loading the footnotes - */ - public void testLoadFootnotesOnce() throws IOException{ - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug54849.docx"); - List footnotes = doc.getFootnotes(); - int hits = 0; - for (XWPFFootnote fn : footnotes){ - for (IBodyElement e : fn.getBodyElements()){ - if (e instanceof XWPFParagraph){ - String txt = ((XWPFParagraph)e).getText(); - if (txt.indexOf("Footnote_sdt") > -1){ - hits++; - } - } - } - } - assertEquals("Load footnotes once", 1, hits); - } -} - +import java.util.List; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFtnEdn; + +public class TestXWPFFootnotes extends TestCase { + + public void testAddFootnotesToDocument() throws IOException { + XWPFDocument docOut = new XWPFDocument(); + + BigInteger noteId = BigInteger.valueOf(1); + + XWPFFootnotes footnotes = docOut.createFootnotes(); + CTFtnEdn ctNote = CTFtnEdn.Factory.newInstance(); + ctNote.setId(noteId); + ctNote.setType(STFtnEdn.NORMAL); + footnotes.addFootnote(ctNote); + + XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut); + + XWPFFootnote note = docIn.getFootnoteByID(noteId.intValue()); + assertEquals(note.getCTFtnEdn().getType(), STFtnEdn.NORMAL); + } + + /** + * Bug 55066 - avoid double loading the footnotes + */ + public void testLoadFootnotesOnce() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug54849.docx"); + List footnotes = doc.getFootnotes(); + int hits = 0; + for (XWPFFootnote fn : footnotes) { + for (IBodyElement e : fn.getBodyElements()) { + if (e instanceof XWPFParagraph) { + String txt = ((XWPFParagraph) e).getText(); + if (txt.indexOf("Footnote_sdt") > -1) { + hits++; + } + } + } + } + assertEquals("Load footnotes once", 1, hits); + } +} + diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeader.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeader.java index a607d0e3f..172c0eb16 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeader.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeader.java @@ -17,13 +17,12 @@ package org.apache.poi.xwpf.usermodel; -import java.io.IOException; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; -import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText; @@ -159,25 +158,25 @@ public final class TestXWPFHeader extends TestCase { assertEquals("First paragraph for the footer", paras[0].getText()); assertEquals("Second paragraph for the footer", paras[1].getText()); } - - public void testSetWatermark() throws IOException { - XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx"); - - // No header is set (yet) - XWPFHeaderFooterPolicy policy = sampleDoc.getHeaderFooterPolicy(); - assertNull(policy.getDefaultHeader()); + + public void testSetWatermark() throws IOException { + XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx"); + + // No header is set (yet) + XWPFHeaderFooterPolicy policy = sampleDoc.getHeaderFooterPolicy(); + assertNull(policy.getDefaultHeader()); assertNull(policy.getFirstPageHeader()); assertNull(policy.getDefaultFooter()); policy.createWatermark("DRAFT"); - assertNotNull(policy.getDefaultHeader()); - assertNotNull(policy.getFirstPageHeader()); - assertNotNull(policy.getEvenPageHeader()); - - // Re-open, and check - XWPFDocument reopened = XWPFTestDataSamples.writeOutAndReadBack(sampleDoc); - policy = reopened.getHeaderFooterPolicy(); + assertNotNull(policy.getDefaultHeader()); + assertNotNull(policy.getFirstPageHeader()); + assertNotNull(policy.getEvenPageHeader()); + + // Re-open, and check + XWPFDocument reopened = XWPFTestDataSamples.writeOutAndReadBack(sampleDoc); + policy = reopened.getHeaderFooterPolicy(); assertNotNull(policy.getDefaultHeader()); assertNotNull(policy.getFirstPageHeader()); diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeadings.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeadings.java index ca74d81e2..b08463482 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeadings.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFHeadings.java @@ -16,39 +16,38 @@ ==================================================================== */ package org.apache.poi.xwpf.usermodel; -import java.io.IOException; +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.apache.xmlbeans.XmlException; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; -import org.apache.xmlbeans.XmlException; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock; - -/** - * @author Paolo Mottadelli - */ -public final class TestXWPFHeadings extends TestCase{ - private static final String HEADING1 = "Heading1"; - - public void testSetParagraphStyle() throws IOException, XmlException { - //new clean instance of paragraph - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("heading123.docx"); - XWPFParagraph p = doc.createParagraph(); - XWPFRun run = p.createRun(); - run.setText("Heading 1"); - - CTSdtBlock block = doc.getDocument().getBody().addNewSdt(); - - assertNull(p.getStyle()); - p.setStyle(HEADING1); - assertEquals(HEADING1, p.getCTP().getPPr().getPStyle().getVal()); - - doc.createTOC(); - /* - // TODO - finish this test - if (false) { - CTStyles styles = doc.getStyle(); - CTStyle style = styles.addNewStyle(); +/** + * @author Paolo Mottadelli + */ +public final class TestXWPFHeadings extends TestCase { + private static final String HEADING1 = "Heading1"; + + public void testSetParagraphStyle() throws IOException, XmlException { + //new clean instance of paragraph + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("heading123.docx"); + XWPFParagraph p = doc.createParagraph(); + XWPFRun run = p.createRun(); + run.setText("Heading 1"); + + CTSdtBlock block = doc.getDocument().getBody().addNewSdt(); + + assertNull(p.getStyle()); + p.setStyle(HEADING1); + assertEquals(HEADING1, p.getCTP().getPPr().getPStyle().getVal()); + + doc.createTOC(); + /* + // TODO - finish this test + if (false) { + CTStyles styles = doc.getStyle(); + CTStyle style = styles.addNewStyle(); style.setType(STStyleType.PARAGRAPH); style.setStyleId("Heading1"); } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFNumbering.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFNumbering.java index fce9d18e0..dfdecc9f3 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFNumbering.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFNumbering.java @@ -18,60 +18,85 @@ package org.apache.poi.xwpf.usermodel; import java.io.IOException; -import java.math.BigInteger; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; - -public class TestXWPFNumbering extends TestCase { - - public void testCompareAbstractNum() throws IOException{ - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); - XWPFNumbering numbering = doc.getNumbering(); - BigInteger numId = BigInteger.valueOf(1); - assertTrue(numbering.numExist(numId)); - XWPFNum num = numbering.getNum(numId); - BigInteger abstrNumId = num.getCTNum().getAbstractNumId().getVal(); - XWPFAbstractNum abstractNum = numbering.getAbstractNum(abstrNumId); - BigInteger compareAbstractNum = numbering.getIdOfAbstractNum(abstractNum); - assertEquals(abstrNumId, compareAbstractNum); - } - - public void testAddNumberingToDoc() throws IOException{ - BigInteger abstractNumId = BigInteger.valueOf(1); - BigInteger numId = BigInteger.valueOf(1); - - XWPFDocument docOut = new XWPFDocument(); - XWPFNumbering numbering = docOut.createNumbering(); - numId = numbering.addNum(abstractNumId); - - XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut); - - numbering = docIn.getNumbering(); - assertTrue(numbering.numExist(numId)); - XWPFNum num = numbering.getNum(numId); - - BigInteger compareAbstractNum = num.getCTNum().getAbstractNumId().getVal(); - assertEquals(abstractNumId, compareAbstractNum); - } - - public void testGetNumIlvl() throws IOException{ - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); - BigInteger numIlvl = BigInteger.valueOf(0); - assertEquals(numIlvl, doc.getParagraphs().get(0).getNumIlvl()); - numIlvl = BigInteger.valueOf(1); - assertEquals(numIlvl, doc.getParagraphs().get(5).getNumIlvl()); - } - - public void testGetNumFmt() throws IOException{ - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); - assertEquals("bullet", doc.getParagraphs().get(0).getNumFmt()); - assertEquals("bullet", doc.getParagraphs().get(1).getNumFmt()); - assertEquals("bullet", doc.getParagraphs().get(2).getNumFmt()); - assertEquals("bullet", doc.getParagraphs().get(3).getNumFmt()); - assertEquals("decimal", doc.getParagraphs().get(4).getNumFmt()); - assertEquals("lowerLetter", doc.getParagraphs().get(5).getNumFmt()); - assertEquals("lowerRoman", doc.getParagraphs().get(6).getNumFmt()); - } -} +import java.math.BigInteger; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNum; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumLvl; + +public class TestXWPFNumbering extends TestCase { + + public void testCompareAbstractNum() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); + XWPFNumbering numbering = doc.getNumbering(); + BigInteger numId = BigInteger.valueOf(1); + assertTrue(numbering.numExist(numId)); + XWPFNum num = numbering.getNum(numId); + BigInteger abstrNumId = num.getCTNum().getAbstractNumId().getVal(); + XWPFAbstractNum abstractNum = numbering.getAbstractNum(abstrNumId); + BigInteger compareAbstractNum = numbering.getIdOfAbstractNum(abstractNum); + assertEquals(abstrNumId, compareAbstractNum); + } + + public void testAddNumberingToDoc() throws IOException { + BigInteger abstractNumId = BigInteger.valueOf(1); + BigInteger numId = BigInteger.valueOf(1); + + XWPFDocument docOut = new XWPFDocument(); + XWPFNumbering numbering = docOut.createNumbering(); + numId = numbering.addNum(abstractNumId); + + XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut); + + numbering = docIn.getNumbering(); + assertTrue(numbering.numExist(numId)); + XWPFNum num = numbering.getNum(numId); + + BigInteger compareAbstractNum = num.getCTNum().getAbstractNumId().getVal(); + assertEquals(abstractNumId, compareAbstractNum); + } + + public void testGetNumIlvl() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); + BigInteger numIlvl = BigInteger.valueOf(0); + assertEquals(numIlvl, doc.getParagraphs().get(0).getNumIlvl()); + numIlvl = BigInteger.valueOf(1); + assertEquals(numIlvl, doc.getParagraphs().get(5).getNumIlvl()); + } + + public void testGetNumFmt() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); + assertEquals("bullet", doc.getParagraphs().get(0).getNumFmt()); + assertEquals("bullet", doc.getParagraphs().get(1).getNumFmt()); + assertEquals("bullet", doc.getParagraphs().get(2).getNumFmt()); + assertEquals("bullet", doc.getParagraphs().get(3).getNumFmt()); + assertEquals("decimal", doc.getParagraphs().get(4).getNumFmt()); + assertEquals("lowerLetter", doc.getParagraphs().get(5).getNumFmt()); + assertEquals("lowerRoman", doc.getParagraphs().get(6).getNumFmt()); + } + + public void testLvlText() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Numbering.docx"); + + assertEquals("%1.%2.%3.", doc.getParagraphs().get(12).getNumLevelText()); + + assertEquals("NEW-%1-FORMAT", doc.getParagraphs().get(14).getNumLevelText()); + + XWPFParagraph p = doc.getParagraphs().get(18); + assertEquals("%1.", p.getNumLevelText()); + //test that null doesn't throw NPE + assertNull(p.getNumFmt()); + } + + public void testOverrideList() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("NumberingWOverrides.docx"); + XWPFParagraph p = doc.getParagraphs().get(4); + XWPFNumbering numbering = doc.getNumbering(); + CTNum ctNum = numbering.getNum(p.getNumID()).getCTNum(); + assertEquals(9, ctNum.sizeOfLvlOverrideArray()); + CTNumLvl ctNumLvl = ctNum.getLvlOverrideArray(0); + assertEquals("upperLetter", ctNumLvl.getLvl().getNumFmt().getVal().toString()); + } + +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFParagraph.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFParagraph.java index ec17da408..31be821e0 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFParagraph.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFParagraph.java @@ -22,12 +22,26 @@ import java.math.BigInteger; import java.util.List; import junit.framework.TestCase; - import org.apache.poi.xwpf.XWPFTestDataSamples; import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture; import org.openxmlformats.schemas.drawingml.x2006.picture.PicDocument; import org.openxmlformats.schemas.drawingml.x2006.picture.impl.PicDocumentImpl; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTInd; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJc; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPBdr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTextAlignment; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTextAlignment; /** * Tests for XWPF Paragraphs @@ -36,7 +50,8 @@ public final class TestXWPFParagraph extends TestCase { /** * Check that we get the right paragraph from the header - * @throws IOException + * + * @throws IOException */ public void disabled_testHeaderParagraph() throws IOException { XWPFDocument xml = XWPFTestDataSamples.openSampleDocument("ThreeColHead.docx"); @@ -44,7 +59,7 @@ public final class TestXWPFParagraph extends TestCase { XWPFHeader hdr = xml.getHeaderFooterPolicy().getDefaultHeader(); assertNotNull(hdr); - List ps = hdr.getParagraphs(); + List ps = hdr.getParagraphs(); assertEquals(1, ps.size()); XWPFParagraph p = ps.get(0); @@ -55,7 +70,8 @@ public final class TestXWPFParagraph extends TestCase { /** * Check that we get the right paragraphs from the document - * @throws IOException + * + * @throws IOException */ public void disabled_testDocumentParagraph() throws IOException { XWPFDocument xml = XWPFTestDataSamples.openSampleDocument("ThreeColHead.docx"); @@ -88,7 +104,7 @@ public final class TestXWPFParagraph extends TestCase { assertEquals(STBorder.NONE.intValue(), p.getBorderTop().getValue()); CTP ctp = p.getCTP(); - CTPPr ppr = ctp.getPPr()== null? ctp.addNewPPr() : ctp.getPPr(); + CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr(); //bordi CTPBdr bdr = ppr.addNewPBdr(); @@ -109,7 +125,7 @@ public final class TestXWPFParagraph extends TestCase { assertEquals(STJc.LEFT.intValue(), p.getAlignment().getValue()); CTP ctp = p.getCTP(); - CTPPr ppr = ctp.getPPr()== null? ctp.addNewPPr() : ctp.getPPr(); + CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr(); CTJc align = ppr.addNewJc(); align.setVal(STJc.CENTER); @@ -125,7 +141,7 @@ public final class TestXWPFParagraph extends TestCase { XWPFParagraph p = doc.createParagraph(); CTP ctp = p.getCTP(); - CTPPr ppr = ctp.getPPr()== null? ctp.addNewPPr() : ctp.getPPr(); + CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr(); assertEquals(-1, p.getSpacingAfter()); @@ -142,7 +158,7 @@ public final class TestXWPFParagraph extends TestCase { XWPFParagraph p = doc.createParagraph(); CTP ctp = p.getCTP(); - CTPPr ppr = ctp.getPPr()== null? ctp.addNewPPr() : ctp.getPPr(); + CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr(); assertEquals(STLineSpacingRule.INT_AUTO, p.getSpacingLineRule().getValue()); @@ -161,7 +177,7 @@ public final class TestXWPFParagraph extends TestCase { assertEquals(-1, p.getIndentationLeft()); CTP ctp = p.getCTP(); - CTPPr ppr = ctp.getPPr()== null? ctp.addNewPPr() : ctp.getPPr(); + CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr(); assertEquals(-1, p.getIndentationLeft()); @@ -179,7 +195,7 @@ public final class TestXWPFParagraph extends TestCase { XWPFParagraph p = doc.createParagraph(); CTP ctp = p.getCTP(); - CTPPr ppr = ctp.getPPr()== null? ctp.addNewPPr() : ctp.getPPr(); + CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr(); CTTextAlignment txtAlign = ppr.addNewTextAlignment(); txtAlign.setVal(STTextAlignment.CENTER); @@ -194,7 +210,7 @@ public final class TestXWPFParagraph extends TestCase { XWPFParagraph p = doc.createParagraph(); CTP ctp = p.getCTP(); - CTPPr ppr = ctp.getPPr()== null? ctp.addNewPPr() : ctp.getPPr(); + CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr(); CTOnOff wordWrap = ppr.addNewWordWrap(); wordWrap.setVal(STOnOff.FALSE); @@ -210,7 +226,7 @@ public final class TestXWPFParagraph extends TestCase { XWPFParagraph p = doc.createParagraph(); CTP ctp = p.getCTP(); - CTPPr ppr = ctp.getPPr()== null? ctp.addNewPPr() : ctp.getPPr(); + CTPPr ppr = ctp.getPPr() == null ? ctp.addNewPPr() : ctp.getPPr(); CTOnOff pageBreak = ppr.addNewPageBreakBefore(); pageBreak.setVal(STOnOff.FALSE); @@ -229,8 +245,8 @@ public final class TestXWPFParagraph extends TestCase { assertEquals(0, paragraph.getCTP().sizeOfBookmarkEndArray()); CTBookmark ctBookmark = paragraph.getCTP().getBookmarkStartArray(0); assertEquals("poi", ctBookmark.getName()); - for(CTBookmark bookmark : paragraph.getCTP().getBookmarkStartArray()) { - assertEquals("poi", bookmark.getName()); + for (CTBookmark bookmark : paragraph.getCTP().getBookmarkStartArray()) { + assertEquals("poi", bookmark.getName()); } } @@ -241,108 +257,108 @@ public final class TestXWPFParagraph extends TestCase { p.setNumID(new BigInteger("10")); assertEquals("10", p.getNumID().toString()); } - + public void testAddingRuns() throws Exception { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); - - XWPFParagraph p = doc.getParagraphs().get(0); - assertEquals(2, p.getRuns().size()); - - XWPFRun r = p.createRun(); - assertEquals(3, p.getRuns().size()); - assertEquals(2, p.getRuns().indexOf(r)); - - XWPFRun r2 = p.insertNewRun(1); - assertEquals(4, p.getRuns().size()); - assertEquals(1, p.getRuns().indexOf(r2)); - assertEquals(3, p.getRuns().indexOf(r)); + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); + + XWPFParagraph p = doc.getParagraphs().get(0); + assertEquals(2, p.getRuns().size()); + + XWPFRun r = p.createRun(); + assertEquals(3, p.getRuns().size()); + assertEquals(2, p.getRuns().indexOf(r)); + + XWPFRun r2 = p.insertNewRun(1); + assertEquals(4, p.getRuns().size()); + assertEquals(1, p.getRuns().indexOf(r2)); + assertEquals(3, p.getRuns().indexOf(r)); } - + public void testPictures() throws Exception { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("VariousPictures.docx"); - assertEquals(7, doc.getParagraphs().size()); - - XWPFParagraph p; - XWPFRun r; + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("VariousPictures.docx"); + assertEquals(7, doc.getParagraphs().size()); - // Text paragraphs - assertEquals("Sheet with various pictures", doc.getParagraphs().get(0).getText()); - assertEquals("(jpeg, png, wmf, emf and pict) ", doc.getParagraphs().get(1).getText()); - - // Spacer ones - assertEquals("", doc.getParagraphs().get(2).getText()); - assertEquals("", doc.getParagraphs().get(3).getText()); - assertEquals("", doc.getParagraphs().get(4).getText()); - - // Image one - p = doc.getParagraphs().get(5); - assertEquals(6, p.getRuns().size()); + XWPFParagraph p; + XWPFRun r; - r = p.getRuns().get(0); - assertEquals("", r.toString()); - assertEquals(1, r.getEmbeddedPictures().size()); - assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); - assertEquals("image1.wmf", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); + // Text paragraphs + assertEquals("Sheet with various pictures", doc.getParagraphs().get(0).getText()); + assertEquals("(jpeg, png, wmf, emf and pict) ", doc.getParagraphs().get(1).getText()); - r = p.getRuns().get(1); - assertEquals("", r.toString()); - assertEquals(1, r.getEmbeddedPictures().size()); - assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); - assertEquals("image2.png", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); + // Spacer ones + assertEquals("", doc.getParagraphs().get(2).getText()); + assertEquals("", doc.getParagraphs().get(3).getText()); + assertEquals("", doc.getParagraphs().get(4).getText()); - r = p.getRuns().get(2); - assertEquals("", r.toString()); - assertEquals(1, r.getEmbeddedPictures().size()); - assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); - assertEquals("image3.emf", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); + // Image one + p = doc.getParagraphs().get(5); + assertEquals(6, p.getRuns().size()); - r = p.getRuns().get(3); - assertEquals("", r.toString()); - assertEquals(1, r.getEmbeddedPictures().size()); - assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); - assertEquals("image4.emf", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); + r = p.getRuns().get(0); + assertEquals("", r.toString()); + assertEquals(1, r.getEmbeddedPictures().size()); + assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); + assertEquals("image1.wmf", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); - r = p.getRuns().get(4); - assertEquals("", r.toString()); - assertEquals(1, r.getEmbeddedPictures().size()); - assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); - assertEquals("image5.jpeg", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); - - r = p.getRuns().get(5); - assertEquals(" ", r.toString()); - assertEquals(0, r.getEmbeddedPictures().size()); - - // Final spacer - assertEquals("", doc.getParagraphs().get(6).getText()); - - - // Look in detail at one - r = p.getRuns().get(4); - XWPFPicture pict = r.getEmbeddedPictures().get(0); - CTPicture picture = pict.getCTPicture(); - assertEquals("rId8", picture.getBlipFill().getBlip().getEmbed()); - - // Ensure that the ooxml compiler finds everything we need - r.getCTR().getDrawingArray(0); - r.getCTR().getDrawingArray(0).getInlineArray(0); - r.getCTR().getDrawingArray(0).getInlineArray(0).getGraphic(); - r.getCTR().getDrawingArray(0).getInlineArray(0).getGraphic().getGraphicData(); - PicDocument pd = new PicDocumentImpl(null); - assertTrue(pd.isNil()); + r = p.getRuns().get(1); + assertEquals("", r.toString()); + assertEquals(1, r.getEmbeddedPictures().size()); + assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); + assertEquals("image2.png", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); + + r = p.getRuns().get(2); + assertEquals("", r.toString()); + assertEquals(1, r.getEmbeddedPictures().size()); + assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); + assertEquals("image3.emf", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); + + r = p.getRuns().get(3); + assertEquals("", r.toString()); + assertEquals(1, r.getEmbeddedPictures().size()); + assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); + assertEquals("image4.emf", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); + + r = p.getRuns().get(4); + assertEquals("", r.toString()); + assertEquals(1, r.getEmbeddedPictures().size()); + assertNotNull(r.getEmbeddedPictures().get(0).getPictureData()); + assertEquals("image5.jpeg", r.getEmbeddedPictures().get(0).getPictureData().getFileName()); + + r = p.getRuns().get(5); + assertEquals(" ", r.toString()); + assertEquals(0, r.getEmbeddedPictures().size()); + + // Final spacer + assertEquals("", doc.getParagraphs().get(6).getText()); + + + // Look in detail at one + r = p.getRuns().get(4); + XWPFPicture pict = r.getEmbeddedPictures().get(0); + CTPicture picture = pict.getCTPicture(); + assertEquals("rId8", picture.getBlipFill().getBlip().getEmbed()); + + // Ensure that the ooxml compiler finds everything we need + r.getCTR().getDrawingArray(0); + r.getCTR().getDrawingArray(0).getInlineArray(0); + r.getCTR().getDrawingArray(0).getInlineArray(0).getGraphic(); + r.getCTR().getDrawingArray(0).getInlineArray(0).getGraphic().getGraphicData(); + PicDocument pd = new PicDocumentImpl(null); + assertTrue(pd.isNil()); } - - public void testTika792() throws Exception{ - //This test forces the loading of CTMoveBookmark and - //CTMoveBookmarkImpl into ooxml-lite. - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Tika-792.docx"); - XWPFParagraph paragraph = doc.getParagraphs().get(0); - assertEquals("s", paragraph.getText()); + + public void testTika792() throws Exception { + //This test forces the loading of CTMoveBookmark and + //CTMoveBookmarkImpl into ooxml-lite. + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Tika-792.docx"); + XWPFParagraph paragraph = doc.getParagraphs().get(0); + assertEquals("s", paragraph.getText()); } public void testSettersGetters() { XWPFDocument doc = new XWPFDocument(); XWPFParagraph p = doc.createParagraph(); - + assertTrue(p.isEmpty()); assertFalse(p.removeRun(0)); @@ -355,7 +371,7 @@ public final class TestXWPFParagraph extends TestCase { assertFalse(p.isEmpty()); assertNull(p.getStyleID()); assertNull(p.getStyle()); - + assertNull(p.getNumID()); p.setNumID(BigInteger.valueOf(12)); assertEquals(BigInteger.valueOf(12), p.getNumID()); @@ -363,18 +379,18 @@ public final class TestXWPFParagraph extends TestCase { assertEquals(BigInteger.valueOf(13), p.getNumID()); assertNull(p.getNumFmt()); - + assertNull(p.getNumIlvl()); - + assertEquals("", p.getParagraphText()); assertEquals("", p.getPictureText()); assertEquals("", p.getFootnoteText()); - + p.setBorderBetween(Borders.NONE); assertEquals(Borders.NONE, p.getBorderBetween()); p.setBorderBetween(Borders.BASIC_BLACK_DASHES); assertEquals(Borders.BASIC_BLACK_DASHES, p.getBorderBetween()); - + p.setBorderBottom(Borders.NONE); assertEquals(Borders.NONE, p.getBorderBottom()); p.setBorderBottom(Borders.BABY_RATTLE); @@ -394,37 +410,37 @@ public final class TestXWPFParagraph extends TestCase { assertEquals(Borders.NONE, p.getBorderBottom()); p.setBorderBottom(Borders.BASIC_WHITE_DOTS); assertEquals(Borders.BASIC_WHITE_DOTS, p.getBorderBottom()); - + assertFalse(p.isPageBreak()); p.setPageBreak(true); assertTrue(p.isPageBreak()); p.setPageBreak(false); assertFalse(p.isPageBreak()); - + assertEquals(-1, p.getSpacingAfter()); p.setSpacingAfter(12); assertEquals(12, p.getSpacingAfter()); - + assertEquals(-1, p.getSpacingAfterLines()); p.setSpacingAfterLines(14); assertEquals(14, p.getSpacingAfterLines()); - + assertEquals(-1, p.getSpacingBefore()); p.setSpacingBefore(16); assertEquals(16, p.getSpacingBefore()); - + assertEquals(-1, p.getSpacingBeforeLines()); p.setSpacingBeforeLines(18); assertEquals(18, p.getSpacingBeforeLines()); - + assertEquals(LineSpacingRule.AUTO, p.getSpacingLineRule()); p.setSpacingLineRule(LineSpacingRule.EXACT); assertEquals(LineSpacingRule.EXACT, p.getSpacingLineRule()); - + assertEquals(-1, p.getIndentationLeft()); p.setIndentationLeft(21); assertEquals(21, p.getIndentationLeft()); - + assertEquals(-1, p.getIndentationRight()); p.setIndentationRight(25); assertEquals(25, p.getIndentationRight()); @@ -442,20 +458,20 @@ public final class TestXWPFParagraph extends TestCase { assertTrue(p.isWordWrap()); p.setWordWrap(false); assertFalse(p.isWordWrap()); - + assertNull(p.getStyle()); p.setStyle("teststyle"); assertEquals("teststyle", p.getStyle()); - + p.addRun(CTR.Factory.newInstance()); - + //assertTrue(p.removeRun(0)); - + assertNotNull(p.getBody()); assertEquals(BodyElementType.PARAGRAPH, p.getElementType()); assertEquals(BodyType.DOCUMENT, p.getPartType()); } - + public void testSearchTextNotFound() { XWPFDocument doc = new XWPFDocument(); XWPFParagraph p = doc.createParagraph(); @@ -469,17 +485,17 @@ public final class TestXWPFParagraph extends TestCase { List ps = xml.getParagraphs(); assertEquals(10, ps.size()); - + XWPFParagraph p = ps.get(0); TextSegement segment = p.searchText("sample word document", new PositionInParagraph()); assertNotNull(segment); - + assertEquals("sample word document", p.getText(segment)); - + assertTrue(p.removeRun(0)); } - + @SuppressWarnings("deprecation") public void testRuns() { XWPFDocument doc = new XWPFDocument(); @@ -489,7 +505,7 @@ public final class TestXWPFParagraph extends TestCase { XWPFRun r = new XWPFRun(run, doc.createParagraph()); p.addRun(r); p.addRun(r); - + assertNotNull(p.getRun(run)); assertNull(p.getRun(null)); } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java index 34a47fdfb..c9123a3a1 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java @@ -20,138 +20,129 @@ package org.apache.poi.xwpf.usermodel; import static org.junit.Assert.assertArrayEquals; import java.io.IOException; -import java.util.List; - -import junit.framework.TestCase; - -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.xssf.usermodel.XSSFRelation; +import java.util.List; + +import junit.framework.TestCase; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.xssf.usermodel.XSSFRelation; import org.apache.poi.xwpf.XWPFTestDataSamples; -import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; - -public class TestXWPFPictureData extends TestCase { - - public void testRead() throws InvalidFormatException, IOException - { - XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("VariousPictures.docx"); - List pictures = sampleDoc.getAllPictures(); - - assertEquals(5,pictures.size()); - String[] ext = {"wmf","png","emf","emf","jpeg"}; - for (int i = 0 ; i < pictures.size() ; i++) - { - assertEquals(ext[i],pictures.get(i).suggestFileExtension()); - } - - int num = pictures.size(); - - byte[] pictureData = XWPFTestDataSamples.getImage("nature1.jpg"); - - String relationId = sampleDoc.addPictureData(pictureData,XWPFDocument.PICTURE_TYPE_JPEG); - // picture list was updated - assertEquals(num + 1,pictures.size()); - XWPFPictureData pict = (XWPFPictureData) sampleDoc.getRelationById(relationId); - assertEquals("jpeg",pict.suggestFileExtension()); - assertArrayEquals(pictureData,pict.getData()); - } - - public void testPictureInHeader() throws IOException - { - XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("headerPic.docx"); - verifyOneHeaderPicture(sampleDoc); - - XWPFDocument readBack = XWPFTestDataSamples.writeOutAndReadBack(sampleDoc); - verifyOneHeaderPicture(readBack); - } +import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; + +public class TestXWPFPictureData extends TestCase { + + public void testRead() throws InvalidFormatException, IOException { + XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("VariousPictures.docx"); + List pictures = sampleDoc.getAllPictures(); + + assertEquals(5, pictures.size()); + String[] ext = {"wmf", "png", "emf", "emf", "jpeg"}; + for (int i = 0; i < pictures.size(); i++) { + assertEquals(ext[i], pictures.get(i).suggestFileExtension()); + } + + int num = pictures.size(); + + byte[] pictureData = XWPFTestDataSamples.getImage("nature1.jpg"); + + String relationId = sampleDoc.addPictureData(pictureData, XWPFDocument.PICTURE_TYPE_JPEG); + // picture list was updated + assertEquals(num + 1, pictures.size()); + XWPFPictureData pict = (XWPFPictureData) sampleDoc.getRelationById(relationId); + assertEquals("jpeg", pict.suggestFileExtension()); + assertArrayEquals(pictureData, pict.getData()); + } + + public void testPictureInHeader() throws IOException { + XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("headerPic.docx"); + verifyOneHeaderPicture(sampleDoc); + + XWPFDocument readBack = XWPFTestDataSamples.writeOutAndReadBack(sampleDoc); + verifyOneHeaderPicture(readBack); + } private void verifyOneHeaderPicture(XWPFDocument sampleDoc) { XWPFHeaderFooterPolicy policy = sampleDoc.getHeaderFooterPolicy(); - XWPFHeader header = policy.getDefaultHeader(); - - List pictures = header.getAllPictures(); - assertEquals(1,pictures.size()); - } - - public void testNew() throws InvalidFormatException, IOException - { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("EmptyDocumentWithHeaderFooter.docx"); - byte[] jpegData = XWPFTestDataSamples.getImage("nature1.jpg"); - assertNotNull(jpegData); + XWPFHeader header = policy.getDefaultHeader(); + + List pictures = header.getAllPictures(); + assertEquals(1, pictures.size()); + } + + public void testNew() throws InvalidFormatException, IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("EmptyDocumentWithHeaderFooter.docx"); + byte[] jpegData = XWPFTestDataSamples.getImage("nature1.jpg"); + assertNotNull(jpegData); byte[] gifData = XWPFTestDataSamples.getImage("nature1.gif"); assertNotNull(gifData); byte[] pngData = XWPFTestDataSamples.getImage("nature1.png"); - assertNotNull(pngData); - - List pictures = doc.getAllPictures(); - assertEquals(0,pictures.size()); - - // Document shouldn't have any image relationships - assertEquals(13,doc.getPackagePart().getRelationships().size()); - for (PackageRelationship rel : doc.getPackagePart().getRelationships()) - { - if (rel.getRelationshipType().equals(XSSFRelation.IMAGE_JPEG.getRelation())) - { - fail("Shouldn't have JPEG yet"); - } - } - - // Add the image - String relationId = doc.addPictureData(jpegData,XWPFDocument.PICTURE_TYPE_JPEG); - assertEquals(1,pictures.size()); - XWPFPictureData jpgPicData = (XWPFPictureData) doc.getRelationById(relationId); - assertEquals("jpeg",jpgPicData.suggestFileExtension()); - assertArrayEquals(jpegData,jpgPicData.getData()); - - // Ensure it now has one - assertEquals(14,doc.getPackagePart().getRelationships().size()); - PackageRelationship jpegRel = null; - for (PackageRelationship rel : doc.getPackagePart().getRelationships()) - { - if (rel.getRelationshipType().equals(XWPFRelation.IMAGE_JPEG.getRelation())) - { - if (jpegRel != null) - fail("Found 2 jpegs!"); - jpegRel = rel; - } - } - assertNotNull("JPEG Relationship not found",jpegRel); - - // Check the details - assertNotNull(jpegRel); - assertEquals(XWPFRelation.IMAGE_JPEG.getRelation(),jpegRel.getRelationshipType()); - assertEquals("/word/document.xml",jpegRel.getSource().getPartName().toString()); - assertEquals("/word/media/image1.jpeg",jpegRel.getTargetURI().getPath()); - - XWPFPictureData pictureDataByID = doc.getPictureDataByID(jpegRel.getId()); - assertArrayEquals(jpegData, pictureDataByID.getData()); - - // Save an re-load, check it appears - doc = XWPFTestDataSamples.writeOutAndReadBack(doc); - assertEquals(1,doc.getAllPictures().size()); - assertEquals(1,doc.getAllPackagePictures().size()); - - // verify the picture that we read back in - pictureDataByID = doc.getPictureDataByID(jpegRel.getId()); - assertArrayEquals(jpegData, pictureDataByID.getData()); - - } - - public void testBug51770() throws InvalidFormatException, IOException { + assertNotNull(pngData); + + List pictures = doc.getAllPictures(); + assertEquals(0, pictures.size()); + + // Document shouldn't have any image relationships + assertEquals(13, doc.getPackagePart().getRelationships().size()); + for (PackageRelationship rel : doc.getPackagePart().getRelationships()) { + if (rel.getRelationshipType().equals(XSSFRelation.IMAGE_JPEG.getRelation())) { + fail("Shouldn't have JPEG yet"); + } + } + + // Add the image + String relationId = doc.addPictureData(jpegData, XWPFDocument.PICTURE_TYPE_JPEG); + assertEquals(1, pictures.size()); + XWPFPictureData jpgPicData = (XWPFPictureData) doc.getRelationById(relationId); + assertEquals("jpeg", jpgPicData.suggestFileExtension()); + assertArrayEquals(jpegData, jpgPicData.getData()); + + // Ensure it now has one + assertEquals(14, doc.getPackagePart().getRelationships().size()); + PackageRelationship jpegRel = null; + for (PackageRelationship rel : doc.getPackagePart().getRelationships()) { + if (rel.getRelationshipType().equals(XWPFRelation.IMAGE_JPEG.getRelation())) { + if (jpegRel != null) + fail("Found 2 jpegs!"); + jpegRel = rel; + } + } + assertNotNull("JPEG Relationship not found", jpegRel); + + // Check the details + assertNotNull(jpegRel); + assertEquals(XWPFRelation.IMAGE_JPEG.getRelation(), jpegRel.getRelationshipType()); + assertEquals("/word/document.xml", jpegRel.getSource().getPartName().toString()); + assertEquals("/word/media/image1.jpeg", jpegRel.getTargetURI().getPath()); + + XWPFPictureData pictureDataByID = doc.getPictureDataByID(jpegRel.getId()); + assertArrayEquals(jpegData, pictureDataByID.getData()); + + // Save an re-load, check it appears + doc = XWPFTestDataSamples.writeOutAndReadBack(doc); + assertEquals(1, doc.getAllPictures().size()); + assertEquals(1, doc.getAllPackagePictures().size()); + + // verify the picture that we read back in + pictureDataByID = doc.getPictureDataByID(jpegRel.getId()); + assertArrayEquals(jpegData, pictureDataByID.getData()); + + } + + public void testBug51770() throws InvalidFormatException, IOException { XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug51170.docx"); XWPFHeaderFooterPolicy policy = doc.getHeaderFooterPolicy(); XWPFHeader header = policy.getDefaultHeader(); for (XWPFParagraph paragraph : header.getParagraphs()) { for (XWPFRun run : paragraph.getRuns()) { for (XWPFPicture picture : run.getEmbeddedPictures()) { - if (paragraph.getDocument() != null) { - //System.out.println(picture.getCTPicture()); - XWPFPictureData data = picture.getPictureData(); - if(data != null) System.out.println(data.getFileName()); - } - } - } + if (paragraph.getDocument() != null) { + //System.out.println(picture.getCTPicture()); + XWPFPictureData data = picture.getPictureData(); + if (data != null) System.out.println(data.getFileName()); + } + } + } } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFRun.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFRun.java index 618618f92..d9af8c91f 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFRun.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFRun.java @@ -20,13 +20,12 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.util.Iterator; -import java.util.List; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; -import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr; +import java.util.List; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBrClear; @@ -46,28 +45,28 @@ public class TestXWPFRun extends TestCase { p = doc.createParagraph(); this.ctRun = CTR.Factory.newInstance(); - } - - public void testSetGetText() { - ctRun.addNewT().setStringValue("TEST STRING"); - ctRun.addNewT().setStringValue("TEST2 STRING"); - ctRun.addNewT().setStringValue("TEST3 STRING"); - - assertEquals(3,ctRun.sizeOfTArray()); - XWPFRun run = new XWPFRun(ctRun, p); - - assertEquals("TEST2 STRING",run.getText(1)); - - run.setText("NEW STRING",0); - assertEquals("NEW STRING",run.getText(0)); - - //run.setText("xxx",14); - //fail("Position wrong"); - } - - public void testSetGetBold() { - CTRPr rpr = ctRun.addNewRPr(); - rpr.addNewB().setVal(STOnOff.TRUE); + } + + public void testSetGetText() { + ctRun.addNewT().setStringValue("TEST STRING"); + ctRun.addNewT().setStringValue("TEST2 STRING"); + ctRun.addNewT().setStringValue("TEST3 STRING"); + + assertEquals(3, ctRun.sizeOfTArray()); + XWPFRun run = new XWPFRun(ctRun, p); + + assertEquals("TEST2 STRING", run.getText(1)); + + run.setText("NEW STRING", 0); + assertEquals("NEW STRING", run.getText(0)); + + //run.setText("xxx",14); + //fail("Position wrong"); + } + + public void testSetGetBold() { + CTRPr rpr = ctRun.addNewRPr(); + rpr.addNewB().setVal(STOnOff.TRUE); XWPFRun run = new XWPFRun(ctRun, p); assertEquals(true, run.isBold()); @@ -178,16 +177,16 @@ public class TestXWPFRun extends TestCase { run.setText("T1"); run.addCarriageReturn(); run.addCarriageReturn(); - run.setText("T2"); - run.addCarriageReturn(); - assertEquals(3, run.getCTR().sizeOfCrArray()); - - assertEquals("T1\n\nT2\n", run.toString()); - } - - public void testAddTabsAndLineBreaks() { - ctRun.addNewT().setStringValue("TEST STRING"); - ctRun.addNewCr(); + run.setText("T2"); + run.addCarriageReturn(); + assertEquals(3, run.getCTR().sizeOfCrArray()); + + assertEquals("T1\n\nT2\n", run.toString()); + } + + public void testAddTabsAndLineBreaks() { + ctRun.addNewT().setStringValue("TEST STRING"); + ctRun.addNewCr(); ctRun.addNewT().setStringValue("TEST2 STRING"); ctRun.addNewTab(); ctRun.addNewT().setStringValue("TEST3 STRING"); @@ -199,21 +198,21 @@ public class TestXWPFRun extends TestCase { run.addCarriageReturn(); run.setText("T2"); run.addTab(); - run.setText("T3"); - assertEquals(1, run.getCTR().sizeOfCrArray()); - assertEquals(1, run.getCTR().sizeOfTabArray()); - - assertEquals("T1\nT2\tT3", run.toString()); - } - + run.setText("T3"); + assertEquals(1, run.getCTR().sizeOfCrArray()); + assertEquals(1, run.getCTR().sizeOfTabArray()); + + assertEquals("T1\nT2\tT3", run.toString()); + } + public void testAddPageBreak() { - ctRun.addNewT().setStringValue("TEST STRING"); - ctRun.addNewBr(); - ctRun.addNewT().setStringValue("TEST2 STRING"); - CTBr breac=ctRun.addNewBr(); - breac.setClear(STBrClear.LEFT); - ctRun.addNewT().setStringValue("TEST3 STRING"); - assertEquals(2, ctRun.sizeOfBrArray()); + ctRun.addNewT().setStringValue("TEST STRING"); + ctRun.addNewBr(); + ctRun.addNewT().setStringValue("TEST2 STRING"); + CTBr breac = ctRun.addNewBr(); + breac.setClear(STBrClear.LEFT); + ctRun.addNewT().setStringValue("TEST3 STRING"); + assertEquals(2, ctRun.sizeOfBrArray()); XWPFRun run = new XWPFRun(CTR.Factory.newInstance(), p); run.setText("TEXT1"); @@ -222,144 +221,145 @@ public class TestXWPFRun extends TestCase { run.addBreak(BreakType.TEXT_WRAPPING); assertEquals(2, run.getCTR().sizeOfBrArray()); } - - /** - * Test that on an existing document, we do the - * right thing with it - * @throws IOException - */ - public void testExisting() throws IOException { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestDocument.docx"); - XWPFParagraph p; - XWPFRun run; - - - // First paragraph is simple - p = doc.getParagraphArray(0); - assertEquals("This is a test document.", p.getText()); - assertEquals(2, p.getRuns().size()); - - run = p.getRuns().get(0); - assertEquals("This is a test document", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - - run = p.getRuns().get(1); - assertEquals(".", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - - - // Next paragraph is all in one style, but a different one - p = doc.getParagraphArray(1); - assertEquals("This bit is in bold and italic", p.getText()); - assertEquals(1, p.getRuns().size()); - - run = p.getRuns().get(0); - assertEquals("This bit is in bold and italic", run.toString()); - assertEquals(true, run.isBold()); - assertEquals(true, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(true, run.getCTR().getRPr().isSetB()); - assertEquals(false, run.getCTR().getRPr().getB().isSetVal()); - - - // Back to normal - p = doc.getParagraphArray(2); - assertEquals("Back to normal", p.getText()); - assertEquals(1, p.getRuns().size()); - - run = p.getRuns().get(0); - assertEquals("Back to normal", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - - - // Different styles in one paragraph - p = doc.getParagraphArray(3); - assertEquals("This contains BOLD, ITALIC and BOTH, as well as RED and YELLOW text.", p.getText()); - assertEquals(11, p.getRuns().size()); - - run = p.getRuns().get(0); - assertEquals("This contains ", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - - run = p.getRuns().get(1); - assertEquals("BOLD", run.toString()); - assertEquals(true, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - - run = p.getRuns().get(2); - assertEquals(", ", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - - run = p.getRuns().get(3); - assertEquals("ITALIC", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(true, run.isItalic()); - assertEquals(false, run.isStrike()); - - run = p.getRuns().get(4); - assertEquals(" and ", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - - run = p.getRuns().get(5); - assertEquals("BOTH", run.toString()); - assertEquals(true, run.isBold()); - assertEquals(true, run.isItalic()); - assertEquals(false, run.isStrike()); - - run = p.getRuns().get(6); - assertEquals(", as well as ", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - - run = p.getRuns().get(7); - assertEquals("RED", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - - run = p.getRuns().get(8); - assertEquals(" and ", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - - run = p.getRuns().get(9); - assertEquals("YELLOW", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - - run = p.getRuns().get(10); - assertEquals(" text.", run.toString()); - assertEquals(false, run.isBold()); - assertEquals(false, run.isItalic()); - assertEquals(false, run.isStrike()); - assertEquals(null, run.getCTR().getRPr()); - } - - public void testPictureInHeader() throws IOException { + + /** + * Test that on an existing document, we do the + * right thing with it + * + * @throws IOException + */ + public void testExisting() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestDocument.docx"); + XWPFParagraph p; + XWPFRun run; + + + // First paragraph is simple + p = doc.getParagraphArray(0); + assertEquals("This is a test document.", p.getText()); + assertEquals(2, p.getRuns().size()); + + run = p.getRuns().get(0); + assertEquals("This is a test document", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + + run = p.getRuns().get(1); + assertEquals(".", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + + + // Next paragraph is all in one style, but a different one + p = doc.getParagraphArray(1); + assertEquals("This bit is in bold and italic", p.getText()); + assertEquals(1, p.getRuns().size()); + + run = p.getRuns().get(0); + assertEquals("This bit is in bold and italic", run.toString()); + assertEquals(true, run.isBold()); + assertEquals(true, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(true, run.getCTR().getRPr().isSetB()); + assertEquals(false, run.getCTR().getRPr().getB().isSetVal()); + + + // Back to normal + p = doc.getParagraphArray(2); + assertEquals("Back to normal", p.getText()); + assertEquals(1, p.getRuns().size()); + + run = p.getRuns().get(0); + assertEquals("Back to normal", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + + + // Different styles in one paragraph + p = doc.getParagraphArray(3); + assertEquals("This contains BOLD, ITALIC and BOTH, as well as RED and YELLOW text.", p.getText()); + assertEquals(11, p.getRuns().size()); + + run = p.getRuns().get(0); + assertEquals("This contains ", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + + run = p.getRuns().get(1); + assertEquals("BOLD", run.toString()); + assertEquals(true, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + + run = p.getRuns().get(2); + assertEquals(", ", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + + run = p.getRuns().get(3); + assertEquals("ITALIC", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(true, run.isItalic()); + assertEquals(false, run.isStrike()); + + run = p.getRuns().get(4); + assertEquals(" and ", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + + run = p.getRuns().get(5); + assertEquals("BOTH", run.toString()); + assertEquals(true, run.isBold()); + assertEquals(true, run.isItalic()); + assertEquals(false, run.isStrike()); + + run = p.getRuns().get(6); + assertEquals(", as well as ", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + + run = p.getRuns().get(7); + assertEquals("RED", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + + run = p.getRuns().get(8); + assertEquals(" and ", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + + run = p.getRuns().get(9); + assertEquals("YELLOW", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + + run = p.getRuns().get(10); + assertEquals(" text.", run.toString()); + assertEquals(false, run.isBold()); + assertEquals(false, run.isItalic()); + assertEquals(false, run.isStrike()); + assertEquals(null, run.getCTR().getRPr()); + } + + public void testPictureInHeader() throws IOException { XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("headerPic.docx"); XWPFHeaderFooterPolicy policy = sampleDoc.getHeaderFooterPolicy(); @@ -373,47 +373,47 @@ public class TestXWPFRun extends TestCase { for (XWPFPicture pic : pictures) { assertNotNull(pic.getPictureData()); - assertEquals("DOZOR", pic.getDescription()); - } - - count+= pictures.size(); - } - } - - assertEquals(1, count); - } - - public void testAddPicture() throws Exception { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestDocument.docx"); - XWPFParagraph p = doc.getParagraphArray(2); - XWPFRun r = p.getRuns().get(0); - - assertEquals(0, doc.getAllPictures().size()); - assertEquals(0, r.getEmbeddedPictures().size()); - - r.addPicture(new ByteArrayInputStream(new byte[0]), Document.PICTURE_TYPE_JPEG, "test.jpg", 21, 32); - - assertEquals(1, doc.getAllPictures().size()); - assertEquals(1, r.getEmbeddedPictures().size()); - } - - /** - * Bugzilla #52288 - setting the font family on the - * run mustn't NPE - */ - public void testSetFontFamily_52288() throws Exception { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("52288.docx"); - final Iterator paragraphs = doc.getParagraphsIterator(); - while (paragraphs.hasNext()) { - final XWPFParagraph paragraph = paragraphs.next(); - for (final XWPFRun run : paragraph.getRuns()) { - if (run != null) { - final String text = run.getText(0); - if (text != null) { - run.setFontFamily("Times New Roman"); - } - } - } - } - } -} + assertEquals("DOZOR", pic.getDescription()); + } + + count += pictures.size(); + } + } + + assertEquals(1, count); + } + + public void testAddPicture() throws Exception { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("TestDocument.docx"); + XWPFParagraph p = doc.getParagraphArray(2); + XWPFRun r = p.getRuns().get(0); + + assertEquals(0, doc.getAllPictures().size()); + assertEquals(0, r.getEmbeddedPictures().size()); + + r.addPicture(new ByteArrayInputStream(new byte[0]), Document.PICTURE_TYPE_JPEG, "test.jpg", 21, 32); + + assertEquals(1, doc.getAllPictures().size()); + assertEquals(1, r.getEmbeddedPictures().size()); + } + + /** + * Bugzilla #52288 - setting the font family on the + * run mustn't NPE + */ + public void testSetFontFamily_52288() throws Exception { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("52288.docx"); + final Iterator paragraphs = doc.getParagraphsIterator(); + while (paragraphs.hasNext()) { + final XWPFParagraph paragraph = paragraphs.next(); + for (final XWPFRun run : paragraph.getRuns()) { + if (run != null) { + final String text = run.getText(0); + if (text != null) { + run.setFontFamily("Times New Roman"); + } + } + } + } + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java index f4114c962..92c94052e 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSDT.java @@ -15,48 +15,46 @@ limitations under the License. ==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; - -public final class TestXWPFSDT extends TestCase { - - /** - * Test simple tag and title extraction from SDT - * @throws Exception - */ - public void testTagTitle() throws Exception { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug54849.docx"); - String tag = null; - String title= null; - List sdts = extractAllSDTs(doc); - for (AbstractXWPFSDT sdt :sdts){ - if (sdt.getContent().toString().equals("Rich_text")){ - tag = "MyTag"; - title = "MyTitle"; - break; - } - - } - assertEquals("controls size", 13, sdts.size()); - +package org.apache.poi.xwpf.usermodel; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; + +public final class TestXWPFSDT extends TestCase { + + /** + * Test simple tag and title extraction from SDT + * + * @throws Exception + */ + public void testTagTitle() throws Exception { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug54849.docx"); + String tag = null; + String title = null; + List sdts = extractAllSDTs(doc); + for (AbstractXWPFSDT sdt : sdts) { + if (sdt.getContent().toString().equals("Rich_text")) { + tag = "MyTag"; + title = "MyTitle"; + break; + } + + } + assertEquals("controls size", 13, sdts.size()); + assertEquals("tag", "MyTag", tag); assertEquals("title", "MyTitle", title); - } - - - public void testGetSDTs() throws Exception{ - String[] contents = new String[]{ - "header_rich_text", - "Rich_text", + } + + + public void testGetSDTs() throws Exception { + String[] contents = new String[]{ + "header_rich_text", + "Rich_text", "Rich_text_pre_table\nRich_text_cell1\t\t\t\n\t\t\t\n\t\t\t\n\nRich_text_post_table", "Plain_text_no_newlines", "Plain_text_with_newlines1\nplain_text_with_newlines2", @@ -72,125 +70,126 @@ public final class TestXWPFSDT extends TestCase { }; XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug54849.docx"); List sdts = extractAllSDTs(doc); - - assertEquals("number of sdts", contents.length, sdts.size()); - - for (int i = 0; i < contents.length; i++){ - AbstractXWPFSDT sdt = sdts.get(i); - assertEquals(i+ ": " + contents[i], contents[i], sdt.getContent().toString()); - } - } - /** - * POI-54771 and TIKA-1317 - */ + + assertEquals("number of sdts", contents.length, sdts.size()); + + for (int i = 0; i < contents.length; i++) { + AbstractXWPFSDT sdt = sdts.get(i); + assertEquals(i + ": " + contents[i], contents[i], sdt.getContent().toString()); + } + } + + /** + * POI-54771 and TIKA-1317 + */ public void testSDTAsCell() throws Exception { //Bug54771a.docx and Bug54771b.docx test slightly //different recursion patterns. Keep both! - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug54771a.docx"); - List sdts = extractAllSDTs(doc); - String text = sdts.get(0).getContent().getText(); - assertEquals(2, sdts.size()); - assertTrue(text.indexOf("Test") > -1); - - text = sdts.get(1).getContent().getText(); + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug54771a.docx"); + List sdts = extractAllSDTs(doc); + String text = sdts.get(0).getContent().getText(); + assertEquals(2, sdts.size()); + assertTrue(text.indexOf("Test") > -1); + + text = sdts.get(1).getContent().getText(); assertTrue(text.indexOf("Test Subtitle") > -1); assertTrue(text.indexOf("Test User") > -1); assertTrue(text.indexOf("Test") < text.indexOf("Test Subtitle")); - - doc = XWPFTestDataSamples.openSampleDocument("Bug54771b.docx"); - sdts = extractAllSDTs(doc); - assertEquals(3, sdts.size()); - assertTrue(sdts.get(0).getContent().getText().indexOf("Test") > -1); - - assertTrue(sdts.get(1).getContent().getText().indexOf("Test Subtitle") > -1); - assertTrue(sdts.get(2).getContent().getText().indexOf("Test User") > -1); - - } - - /** - * POI-55142 and Tika 1130 - */ - public void testNewLinesBetweenRuns() throws Exception{ - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug55142.docx"); - List sdts = extractAllSDTs(doc); - List targs = new ArrayList(); - //these test newlines and tabs in paragraphs/body elements - targs.add("Rich-text1 abcdefghi"); - targs.add("Rich-text2 abcd\t\tefgh"); - targs.add("Rich-text3 abcd\nefg"); - targs.add("Rich-text4 abcdefg"); - targs.add("Rich-text5 abcdefg\nhijk"); - targs.add("Plain-text1 abcdefg"); - targs.add("Plain-text2 abcdefg\nhijk\nlmnop"); - //this tests consecutive runs within a cell (not a paragraph) - //this test case was triggered by Tika-1130 - targs.add("sdt_incell2 abcdefg"); - - for (int i = 0; i < sdts.size(); i++){ - AbstractXWPFSDT sdt = sdts.get(i); - assertEquals(targs.get(i), targs.get(i), sdt.getContent().getText()); - } - } - - private List extractAllSDTs(XWPFDocument doc){ - - List sdts = new ArrayList(); - - List headers = doc.getHeaderList(); - for (XWPFHeader header : headers){ - sdts.addAll(extractSDTsFromBodyElements(header.getBodyElements())); - } - sdts.addAll(extractSDTsFromBodyElements(doc.getBodyElements())); - - List footers = doc.getFooterList(); - for (XWPFFooter footer : footers){ - sdts.addAll(extractSDTsFromBodyElements(footer.getBodyElements())); - } - - for (XWPFFootnote footnote : doc.getFootnotes()){ - sdts.addAll(extractSDTsFromBodyElements(footnote.getBodyElements())); - } - for (Map.Entry e : doc.endnotes.entrySet()){ - sdts.addAll(extractSDTsFromBodyElements(e.getValue().getBodyElements())); - } - return sdts; - } - - private List extractSDTsFromBodyElements(List elements){ - List sdts = new ArrayList(); - for (IBodyElement e : elements){ - if (e instanceof XWPFSDT){ - XWPFSDT sdt = (XWPFSDT)e; - sdts.add(sdt); - } else if (e instanceof XWPFParagraph){ - - XWPFParagraph p = (XWPFParagraph)e; - for (IRunElement e2 : p.getIRuns()){ - if (e2 instanceof XWPFSDT){ - XWPFSDT sdt = (XWPFSDT)e2; - sdts.add(sdt); - } - } - } else if (e instanceof XWPFTable){ - XWPFTable table = (XWPFTable)e; - sdts.addAll(extractSDTsFromTable(table)); - } - } + + doc = XWPFTestDataSamples.openSampleDocument("Bug54771b.docx"); + sdts = extractAllSDTs(doc); + assertEquals(3, sdts.size()); + assertTrue(sdts.get(0).getContent().getText().indexOf("Test") > -1); + + assertTrue(sdts.get(1).getContent().getText().indexOf("Test Subtitle") > -1); + assertTrue(sdts.get(2).getContent().getText().indexOf("Test User") > -1); + + } + + /** + * POI-55142 and Tika 1130 + */ + public void testNewLinesBetweenRuns() throws Exception { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("Bug55142.docx"); + List sdts = extractAllSDTs(doc); + List targs = new ArrayList(); + //these test newlines and tabs in paragraphs/body elements + targs.add("Rich-text1 abcdefghi"); + targs.add("Rich-text2 abcd\t\tefgh"); + targs.add("Rich-text3 abcd\nefg"); + targs.add("Rich-text4 abcdefg"); + targs.add("Rich-text5 abcdefg\nhijk"); + targs.add("Plain-text1 abcdefg"); + targs.add("Plain-text2 abcdefg\nhijk\nlmnop"); + //this tests consecutive runs within a cell (not a paragraph) + //this test case was triggered by Tika-1130 + targs.add("sdt_incell2 abcdefg"); + + for (int i = 0; i < sdts.size(); i++) { + AbstractXWPFSDT sdt = sdts.get(i); + assertEquals(targs.get(i), targs.get(i), sdt.getContent().getText()); + } + } + + private List extractAllSDTs(XWPFDocument doc) { + + List sdts = new ArrayList(); + + List headers = doc.getHeaderList(); + for (XWPFHeader header : headers) { + sdts.addAll(extractSDTsFromBodyElements(header.getBodyElements())); + } + sdts.addAll(extractSDTsFromBodyElements(doc.getBodyElements())); + + List footers = doc.getFooterList(); + for (XWPFFooter footer : footers) { + sdts.addAll(extractSDTsFromBodyElements(footer.getBodyElements())); + } + + for (XWPFFootnote footnote : doc.getFootnotes()) { + sdts.addAll(extractSDTsFromBodyElements(footnote.getBodyElements())); + } + for (Map.Entry e : doc.endnotes.entrySet()) { + sdts.addAll(extractSDTsFromBodyElements(e.getValue().getBodyElements())); + } + return sdts; + } + + private List extractSDTsFromBodyElements(List elements) { + List sdts = new ArrayList(); + for (IBodyElement e : elements) { + if (e instanceof XWPFSDT) { + XWPFSDT sdt = (XWPFSDT) e; + sdts.add(sdt); + } else if (e instanceof XWPFParagraph) { + + XWPFParagraph p = (XWPFParagraph) e; + for (IRunElement e2 : p.getIRuns()) { + if (e2 instanceof XWPFSDT) { + XWPFSDT sdt = (XWPFSDT) e2; + sdts.add(sdt); + } + } + } else if (e instanceof XWPFTable) { + XWPFTable table = (XWPFTable) e; + sdts.addAll(extractSDTsFromTable(table)); + } + } return sdts; } private List extractSDTsFromTable(XWPFTable table) { List sdts = new ArrayList(); - for (XWPFTableRow r : table.getRows()) { - for (ICell c : r.getTableICells()) { - if (c instanceof XWPFSDTCell) { - sdts.add((XWPFSDTCell)c); - } else if (c instanceof XWPFTableCell) { - sdts.addAll(extractSDTsFromBodyElements(((XWPFTableCell)c).getBodyElements())); - } - } - } + for (XWPFTableRow r : table.getRows()) { + for (ICell c : r.getTableICells()) { + if (c instanceof XWPFSDTCell) { + sdts.add((XWPFSDTCell) c); + } else if (c instanceof XWPFTableCell) { + sdts.addAll(extractSDTsFromBodyElements(((XWPFTableCell) c).getBodyElements())); + } + } + } return sdts; } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSmartTag.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSmartTag.java index f12e16805..011092729 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSmartTag.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFSmartTag.java @@ -19,13 +19,12 @@ package org.apache.poi.xwpf.usermodel; import java.io.IOException; import junit.framework.TestCase; - import org.apache.poi.xwpf.XWPFTestDataSamples; /** * Tests for reading SmartTags from Word docx. * - * @author Fabian Lange + * @author Fabian Lange */ public final class TestXWPFSmartTag extends TestCase { diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFStyles.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFStyles.java index c29d50208..bef00de15 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFStyles.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFStyles.java @@ -19,13 +19,12 @@ package org.apache.poi.xwpf.usermodel; import java.io.IOException; import java.util.ArrayList; -import java.util.List; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLatentStyles; +import java.util.List; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLatentStyles; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLsdException; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles; @@ -33,69 +32,69 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.STStyleType; public class TestXWPFStyles extends TestCase { -// protected void setUp() throws Exception { -// super.setUp(); -// } - - public void testGetUsedStyles() throws IOException{ - XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("Styles.docx"); - List testUsedStyleList = new ArrayList(); - XWPFStyles styles = sampleDoc.getStyles(); - XWPFStyle style = styles.getStyle("berschrift1"); - testUsedStyleList.add(style); - testUsedStyleList.add(styles.getStyle("Standard")); - testUsedStyleList.add(styles.getStyle("berschrift1Zchn")); - testUsedStyleList.add(styles.getStyle("Absatz-Standardschriftart")); - style.hasSameName(style); - - List usedStyleList = styles.getUsedStyleList(style); - assertEquals(usedStyleList, testUsedStyleList); - - - } - - public void testAddStylesToDocument() throws IOException{ - XWPFDocument docOut = new XWPFDocument(); - XWPFStyles styles = docOut.createStyles(); - - String strStyleId = "headline1"; - CTStyle ctStyle = CTStyle.Factory.newInstance(); - - ctStyle.setStyleId(strStyleId); - XWPFStyle s = new XWPFStyle(ctStyle); - styles.addStyle(s); - - assertTrue(styles.styleExist(strStyleId)); - - XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut); - - styles = docIn.getStyles(); - assertTrue(styles.styleExist(strStyleId)); - } - - /** - * Bug #52449 - We should be able to write a file containing - * both regular and glossary styles without error - */ - public void test52449() throws Exception { - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("52449.docx"); - XWPFStyles styles = doc.getStyles(); - assertNotNull(styles); - - XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(doc); - styles = docIn.getStyles(); - assertNotNull(styles); - } - - - /** - * YK: tests below don't make much sense, - * they exist only to copy xml beans to pi-ooxml-schemas.jar - */ - public void testLanguages(){ - XWPFDocument docOut = new XWPFDocument(); - XWPFStyles styles = docOut.createStyles(); - styles.setEastAsia("Chinese"); +// protected void setUp() throws Exception { +// super.setUp(); +// } + + public void testGetUsedStyles() throws IOException { + XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("Styles.docx"); + List testUsedStyleList = new ArrayList(); + XWPFStyles styles = sampleDoc.getStyles(); + XWPFStyle style = styles.getStyle("berschrift1"); + testUsedStyleList.add(style); + testUsedStyleList.add(styles.getStyle("Standard")); + testUsedStyleList.add(styles.getStyle("berschrift1Zchn")); + testUsedStyleList.add(styles.getStyle("Absatz-Standardschriftart")); + style.hasSameName(style); + + List usedStyleList = styles.getUsedStyleList(style); + assertEquals(usedStyleList, testUsedStyleList); + + + } + + public void testAddStylesToDocument() throws IOException { + XWPFDocument docOut = new XWPFDocument(); + XWPFStyles styles = docOut.createStyles(); + + String strStyleId = "headline1"; + CTStyle ctStyle = CTStyle.Factory.newInstance(); + + ctStyle.setStyleId(strStyleId); + XWPFStyle s = new XWPFStyle(ctStyle); + styles.addStyle(s); + + assertTrue(styles.styleExist(strStyleId)); + + XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut); + + styles = docIn.getStyles(); + assertTrue(styles.styleExist(strStyleId)); + } + + /** + * Bug #52449 - We should be able to write a file containing + * both regular and glossary styles without error + */ + public void test52449() throws Exception { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("52449.docx"); + XWPFStyles styles = doc.getStyles(); + assertNotNull(styles); + + XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(doc); + styles = docIn.getStyles(); + assertNotNull(styles); + } + + + /** + * YK: tests below don't make much sense, + * they exist only to copy xml beans to pi-ooxml-schemas.jar + */ + public void testLanguages() { + XWPFDocument docOut = new XWPFDocument(); + XWPFStyles styles = docOut.createStyles(); + styles.setEastAsia("Chinese"); styles.setSpellingLanguage("English"); @@ -116,26 +115,82 @@ public class TestXWPFStyles extends TestCase { CTLsdException ex = latentStyles.addNewLsdException(); ex.setName("ex1"); XWPFLatentStyles ls = new XWPFLatentStyles(latentStyles); - assertEquals(true, ls.isLatentStyle("ex1")); - assertEquals(false, ls.isLatentStyle("notex1")); - } - - public void testSetStyles_Bug57254() throws IOException { - XWPFDocument docOut = new XWPFDocument(); - XWPFStyles styles = docOut.createStyles(); + assertEquals(true, ls.isLatentStyle("ex1")); + assertEquals(false, ls.isLatentStyle("notex1")); + } + + public void testSetStyles_Bug57254() throws IOException { + XWPFDocument docOut = new XWPFDocument(); + XWPFStyles styles = docOut.createStyles(); CTStyles ctStyles = CTStyles.Factory.newInstance(); String strStyleId = "headline1"; CTStyle ctStyle = ctStyles.addNewStyle(); + + ctStyle.setStyleId(strStyleId); + styles.setStyles(ctStyles); + + assertTrue(styles.styleExist(strStyleId)); + + XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut); - ctStyle.setStyleId(strStyleId); - styles.setStyles(ctStyles); - - assertTrue(styles.styleExist(strStyleId)); - - XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut); - - styles = docIn.getStyles(); - assertTrue(styles.styleExist(strStyleId)); - } + styles = docIn.getStyles(); + assertTrue(styles.styleExist(strStyleId)); + } + + public void testEasyAccessToStyles() throws IOException { + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx"); + XWPFStyles styles = doc.getStyles(); + assertNotNull(styles); + + // Has 3 paragraphs on page one, a break, and 3 on page 2 + assertEquals(7, doc.getParagraphs().size()); + + // Check the first three have no run styles, just default paragraph style + for (int i = 0; i < 3; i++) { + XWPFParagraph p = doc.getParagraphs().get(i); + assertEquals(null, p.getStyle()); + assertEquals(null, p.getStyleID()); + assertEquals(1, p.getRuns().size()); + + XWPFRun r = p.getRuns().get(0); + assertEquals(null, r.getColor()); + assertEquals(null, r.getFontFamily()); + assertEquals(null, r.getFontName()); + assertEquals(-1, r.getFontSize()); + } + + // On page two, has explicit styles, but on runs not on + // the paragraph itself + for (int i = 4; i < 7; i++) { + XWPFParagraph p = doc.getParagraphs().get(i); + assertEquals(null, p.getStyle()); + assertEquals(null, p.getStyleID()); + assertEquals(1, p.getRuns().size()); + + XWPFRun r = p.getRuns().get(0); + assertEquals("Arial Black", r.getFontFamily()); + assertEquals("Arial Black", r.getFontName()); + assertEquals(16, r.getFontSize()); + assertEquals("548DD4", r.getColor()); + } + + // Check the document styles + // Should have a style defined for each type + assertEquals(4, styles.getNumberOfStyles()); + assertNotNull(styles.getStyle("Normal")); + assertNotNull(styles.getStyle("DefaultParagraphFont")); + assertNotNull(styles.getStyle("TableNormal")); + assertNotNull(styles.getStyle("NoList")); + + // We can't do much yet with latent styles + assertEquals(137, styles.getLatentStyles().getNumberOfStyles()); + + // Check the default styles + assertNotNull(styles.getDefaultRunStyle()); + assertNotNull(styles.getDefaultParagraphStyle()); + + assertEquals(11, styles.getDefaultRunStyle().getFontSize()); + assertEquals(200, styles.getDefaultParagraphStyle().getSpacingAfter()); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTable.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTable.java index 00496b299..6f85a05cf 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTable.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTable.java @@ -17,18 +17,18 @@ package org.apache.poi.xwpf.usermodel; import java.math.BigInteger; -import java.util.List; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.XWPFTestDataSamples; -import org.apache.poi.xwpf.usermodel.XWPFTable.XWPFBorderType; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; +import java.util.List; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.XWPFTestDataSamples; +import org.apache.poi.xwpf.usermodel.XWPFTable.XWPFBorderType; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblCellMar; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder; @@ -64,6 +64,17 @@ public class TestXWPFTable extends TestCase { assertNotNull(ctTable.getTrArray(0).getTcArray(0).getPArray(0)); } + public void testTblGrid() { + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + CTTblGrid cttblgrid = ctTable.addNewTblGrid(); + cttblgrid.addNewGridCol().setW(new BigInteger("123")); + cttblgrid.addNewGridCol().setW(new BigInteger("321")); + + XWPFTable xtab = new XWPFTable(ctTable, doc); + assertEquals(123, xtab.getCTTbl().getTblGrid().getGridColArray(0).getW().intValue()); + assertEquals(321, xtab.getCTTbl().getTblGrid().getGridColArray(1).getW().intValue()); + } public void testGetText() { XWPFDocument doc = new XWPFDocument(); @@ -110,13 +121,13 @@ public class TestXWPFTable extends TestCase { assertEquals(1, xtab.getCTTbl().getTrArray(0).sizeOfTcArray()); } - - public void testSetGetWidth() { - XWPFDocument doc = new XWPFDocument(); - - CTTbl table = CTTbl.Factory.newInstance(); - table.addNewTblPr().addNewTblW().setW(new BigInteger("1000")); - + + public void testSetGetWidth() { + XWPFDocument doc = new XWPFDocument(); + + CTTbl table = CTTbl.Factory.newInstance(); + table.addNewTblPr().addNewTblW().setW(new BigInteger("1000")); + XWPFTable xtab = new XWPFTable(table, doc); assertEquals(1000, xtab.getWidth()); @@ -134,20 +145,20 @@ public class TestXWPFTable extends TestCase { XWPFTableRow row = xtab.createRow(); row.setHeight(20); assertEquals(20, row.getHeight()); - } - - public void testSetGetMargins() { - // instantiate the following class so it'll get picked up by - // the XmlBean process and added to the jar file. it's required - // for the following XWPFTable methods. - CTTblCellMar ctm = CTTblCellMar.Factory.newInstance(); - assertNotNull(ctm); - // create a table - XWPFDocument doc = new XWPFDocument(); - CTTbl ctTable = CTTbl.Factory.newInstance(); - XWPFTable table = new XWPFTable(ctTable, doc); - // set margins - table.setCellMargins(50, 50, 250, 450); + } + + public void testSetGetMargins() { + // instantiate the following class so it'll get picked up by + // the XmlBean process and added to the jar file. it's required + // for the following XWPFTable methods. + CTTblCellMar ctm = CTTblCellMar.Factory.newInstance(); + assertNotNull(ctm); + // create a table + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + XWPFTable table = new XWPFTable(ctTable, doc); + // set margins + table.setCellMargins(50, 50, 250, 450); // get margin components int t = table.getCellMarginTop(); assertEquals(50, t); @@ -157,22 +168,22 @@ public class TestXWPFTable extends TestCase { assertEquals(250, b); int r = table.getCellMarginRight(); assertEquals(450, r); - } - - public void testSetGetHBorders() { - // instantiate the following classes so they'll get picked up by - // the XmlBean process and added to the jar file. they are required - // for the following XWPFTable methods. - CTTblBorders cttb = CTTblBorders.Factory.newInstance(); - assertNotNull(cttb); - STBorder stb = STBorder.Factory.newInstance(); - assertNotNull(stb); - // create a table - XWPFDocument doc = new XWPFDocument(); - CTTbl ctTable = CTTbl.Factory.newInstance(); - XWPFTable table = new XWPFTable(ctTable, doc); - // set inside horizontal border - table.setInsideHBorder(XWPFBorderType.SINGLE, 4, 0, "FF0000"); + } + + public void testSetGetHBorders() { + // instantiate the following classes so they'll get picked up by + // the XmlBean process and added to the jar file. they are required + // for the following XWPFTable methods. + CTTblBorders cttb = CTTblBorders.Factory.newInstance(); + assertNotNull(cttb); + STBorder stb = STBorder.Factory.newInstance(); + assertNotNull(stb); + // create a table + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + XWPFTable table = new XWPFTable(ctTable, doc); + // set inside horizontal border + table.setInsideHBorder(XWPFBorderType.SINGLE, 4, 0, "FF0000"); // get inside horizontal border components int s = table.getInsideHBorderSize(); assertEquals(4, s); @@ -182,26 +193,26 @@ public class TestXWPFTable extends TestCase { assertEquals("FF0000", clr); XWPFBorderType bt = table.getInsideHBorderType(); assertEquals(XWPFBorderType.SINGLE, bt); - } - - public void testSetGetVBorders() { - // create a table - XWPFDocument doc = new XWPFDocument(); - CTTbl ctTable = CTTbl.Factory.newInstance(); - XWPFTable table = new XWPFTable(ctTable, doc); + } + + public void testSetGetVBorders() { + // create a table + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + XWPFTable table = new XWPFTable(ctTable, doc); // set inside vertical border table.setInsideVBorder(XWPFBorderType.DOUBLE, 4, 0, "00FF00"); // get inside vertical border components XWPFBorderType bt = table.getInsideVBorderType(); assertEquals(XWPFBorderType.DOUBLE, bt); int sz = table.getInsideVBorderSize(); - assertEquals(4, sz); - int sp = table.getInsideVBorderSpace(); - assertEquals(0, sp); - String clr = table.getInsideVBorderColor(); - assertEquals("00FF00", clr); - } - + assertEquals(4, sz); + int sp = table.getInsideVBorderSpace(); + assertEquals(0, sp); + String clr = table.getInsideVBorderColor(); + assertEquals("00FF00", clr); + } + public void testSetGetRowBandSize() { XWPFDocument doc = new XWPFDocument(); CTTbl ctTable = CTTbl.Factory.newInstance(); @@ -218,32 +229,30 @@ public class TestXWPFTable extends TestCase { table.setColBandSize(16); int sz = table.getColBandSize(); assertEquals(16, sz); - } - - public void testCreateTable() throws Exception { - // open an empty document - XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); - - // create a table with 5 rows and 7 columns - int noRows = 5; - int noCols = 7; - XWPFTable table = doc.createTable(noRows,noCols); - - // assert the table is empty - List rows = table.getRows(); - assertEquals("Table has less rows than requested.", noRows, rows.size()); - for (XWPFTableRow xwpfRow : rows) - { - assertNotNull(xwpfRow); - for (int i = 0 ; i < 7 ; i++) - { - XWPFTableCell xwpfCell = xwpfRow.getCell(i); - assertNotNull(xwpfCell); - assertEquals("Empty cells should not have one paragraph.",1,xwpfCell.getParagraphs().size()); - xwpfCell = xwpfRow.getCell(i); - assertEquals("Calling 'getCell' must not modify cells content.",1,xwpfCell.getParagraphs().size()); - } - } - doc.getPackage().revert(); - } + } + + public void testCreateTable() throws Exception { + // open an empty document + XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("sample.docx"); + + // create a table with 5 rows and 7 columns + int noRows = 5; + int noCols = 7; + XWPFTable table = doc.createTable(noRows, noCols); + + // assert the table is empty + List rows = table.getRows(); + assertEquals("Table has less rows than requested.", noRows, rows.size()); + for (XWPFTableRow xwpfRow : rows) { + assertNotNull(xwpfRow); + for (int i = 0; i < 7; i++) { + XWPFTableCell xwpfCell = xwpfRow.getCell(i); + assertNotNull(xwpfCell); + assertEquals("Empty cells should not have one paragraph.", 1, xwpfCell.getParagraphs().size()); + xwpfCell = xwpfRow.getCell(i); + assertEquals("Calling 'getCell' must not modify cells content.", 1, xwpfCell.getParagraphs().size()); + } + } + doc.getPackage().revert(); + } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableCell.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableCell.java index 76dfe3822..34d54c041 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableCell.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableCell.java @@ -17,71 +17,80 @@ * ==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -import junit.framework.TestCase; - -import org.apache.poi.xwpf.usermodel.XWPFTableCell.XWPFVertAlign; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; - -public class TestXWPFTableCell extends TestCase { - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - public void testSetGetVertAlignment() throws Exception { - // instantiate the following classes so they'll get picked up by - // the XmlBean process and added to the jar file. they are required - // for the following XWPFTableCell methods. - CTShd ctShd = CTShd.Factory.newInstance(); - assertNotNull(ctShd); - CTVerticalJc ctVjc = CTVerticalJc.Factory.newInstance(); - assertNotNull(ctVjc); - STShd stShd = STShd.Factory.newInstance(); - assertNotNull(stShd); - STVerticalJc stVjc = STVerticalJc.Factory.newInstance(); - assertNotNull(stVjc); - - // create a table - XWPFDocument doc = new XWPFDocument(); - CTTbl ctTable = CTTbl.Factory.newInstance(); - XWPFTable table = new XWPFTable(ctTable, doc); - // table has a single row by default; grab it - XWPFTableRow tr = table.getRow(0); +package org.apache.poi.xwpf.usermodel; + +import junit.framework.TestCase; +import org.apache.poi.xwpf.usermodel.XWPFTableCell.XWPFVertAlign; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHMerge; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTShd; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcBorders; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVerticalJc; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STShd; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; + +public class TestXWPFTableCell extends TestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testSetGetVertAlignment() throws Exception { + // instantiate the following classes so they'll get picked up by + // the XmlBean process and added to the jar file. they are required + // for the following XWPFTableCell methods. + CTShd ctShd = CTShd.Factory.newInstance(); + assertNotNull(ctShd); + CTVerticalJc ctVjc = CTVerticalJc.Factory.newInstance(); + assertNotNull(ctVjc); + STShd stShd = STShd.Factory.newInstance(); + assertNotNull(stShd); + STVerticalJc stVjc = STVerticalJc.Factory.newInstance(); + assertNotNull(stVjc); + + // create a table + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + XWPFTable table = new XWPFTable(ctTable, doc); + // table has a single row by default; grab it + XWPFTableRow tr = table.getRow(0); assertNotNull(tr); // row has a single cell by default; grab it XWPFTableCell cell = tr.getCell(0); - cell.setVerticalAlignment(XWPFVertAlign.BOTH); - XWPFVertAlign al = cell.getVerticalAlignment(); - assertEquals(XWPFVertAlign.BOTH, al); - } - - public void testSetGetColor() throws Exception { - // create a table - XWPFDocument doc = new XWPFDocument(); - CTTbl ctTable = CTTbl.Factory.newInstance(); - XWPFTable table = new XWPFTable(ctTable, doc); - // table has a single row by default; grab it - XWPFTableRow tr = table.getRow(0); + cell.setVerticalAlignment(XWPFVertAlign.BOTH); + XWPFVertAlign al = cell.getVerticalAlignment(); + assertEquals(XWPFVertAlign.BOTH, al); + } + + public void testSetGetColor() throws Exception { + // create a table + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + XWPFTable table = new XWPFTable(ctTable, doc); + // table has a single row by default; grab it + XWPFTableRow tr = table.getRow(0); assertNotNull(tr); // row has a single cell by default; grab it XWPFTableCell cell = tr.getCell(0); - cell.setColor("F0000F"); - String clr = cell.getColor(); - assertEquals("F0000F", clr); - } - - /** - * ensure that CTHMerge & CTTcBorders go in poi-ooxml.jar - */ - public void test54099(){ - XWPFDocument doc = new XWPFDocument(); - CTTbl ctTable = CTTbl.Factory.newInstance(); - XWPFTable table = new XWPFTable(ctTable, doc); + cell.setColor("F0000F"); + String clr = cell.getColor(); + assertEquals("F0000F", clr); + } + + /** + * ensure that CTHMerge & CTTcBorders go in poi-ooxml.jar + */ + public void test54099() { + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + XWPFTable table = new XWPFTable(ctTable, doc); XWPFTableRow tr = table.getRow(0); XWPFTableCell cell = tr.getCell(0); diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableRow.java b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableRow.java index abdf1688c..b01f8e9dc 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableRow.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/usermodel/TestXWPFTableRow.java @@ -15,55 +15,54 @@ limitations under the License. ==================================================================== */ -package org.apache.poi.xwpf.usermodel; - -import junit.framework.TestCase; - -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; -import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; - -public class TestXWPFTableRow extends TestCase { - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - public void testCreateRow() throws Exception { - CTRow ctRow = CTRow.Factory.newInstance(); - assertNotNull(ctRow); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - public void testSetGetCantSplitRow() { - // create a table - XWPFDocument doc = new XWPFDocument(); - CTTbl ctTable = CTTbl.Factory.newInstance(); - XWPFTable table = new XWPFTable(ctTable, doc); - // table has a single row by default; grab it - XWPFTableRow tr = table.getRow(0); - assertNotNull(tr); - - tr.setCantSplitRow(true); - boolean isCant = tr.isCantSplitRow(); - assert(isCant); - } - - public void testSetGetRepeatHeader() { - // create a table - XWPFDocument doc = new XWPFDocument(); - CTTbl ctTable = CTTbl.Factory.newInstance(); - XWPFTable table = new XWPFTable(ctTable, doc); - // table has a single row by default; grab it - XWPFTableRow tr = table.getRow(0); - assertNotNull(tr); - - tr.setRepeatHeader(true); - boolean isRpt = tr.isRepeatHeader(); - assert(isRpt); - } -} +package org.apache.poi.xwpf.usermodel; + +import junit.framework.TestCase; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; + +public class TestXWPFTableRow extends TestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testCreateRow() throws Exception { + CTRow ctRow = CTRow.Factory.newInstance(); + assertNotNull(ctRow); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testSetGetCantSplitRow() { + // create a table + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + XWPFTable table = new XWPFTable(ctTable, doc); + // table has a single row by default; grab it + XWPFTableRow tr = table.getRow(0); + assertNotNull(tr); + + tr.setCantSplitRow(true); + boolean isCant = tr.isCantSplitRow(); + assert (isCant); + } + + public void testSetGetRepeatHeader() { + // create a table + XWPFDocument doc = new XWPFDocument(); + CTTbl ctTable = CTTbl.Factory.newInstance(); + XWPFTable table = new XWPFTable(ctTable, doc); + // table has a single row by default; grab it + XWPFTableRow tr = table.getRow(0); + assertNotNull(tr); + + tr.setRepeatHeader(true); + boolean isRpt = tr.isRepeatHeader(); + assert (isRpt); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hdf/event/EventBridge.java b/src/scratchpad/src/org/apache/poi/hdf/event/EventBridge.java index d4f69476b..c38805c41 100644 --- a/src/scratchpad/src/org/apache/poi/hdf/event/EventBridge.java +++ b/src/scratchpad/src/org/apache/poi/hdf/event/EventBridge.java @@ -21,10 +21,10 @@ package org.apache.poi.hdf.event; import org.apache.poi.hdf.model.util.BTreeSet; import org.apache.poi.hdf.model.util.NumberFormatter; import org.apache.poi.hdf.model.hdftypes.*; - import org.apache.poi.util.LittleEndian; import java.util.ArrayList; +import java.util.List; @Deprecated public final class EventBridge implements HDFLowLevelParsingListener @@ -71,11 +71,11 @@ public final class EventBridge implements HDFLowLevelParsingListener BTreeSet _hdrCharacterRuns = new BTreeSet(); int _sectionCounter = 1; - ArrayList _hdrs = new ArrayList(); + List _hdrs = new ArrayList(); private boolean _holdParagraph = false; private int _endHoldIndex = -1; - private ArrayList _onHold; + private List _onHold; public EventBridge(HDFParsingListener listener) { @@ -119,7 +119,7 @@ public final class EventBridge implements HDFLowLevelParsingListener { for (int x = 1; x < _sectionCounter; x++) { - HeaderFooter[] hdrArray = (HeaderFooter[])_hdrs.get(x-1); + HeaderFooter[] hdrArray = _hdrs.get(x-1); HeaderFooter hf = null; if (!hdrArray[HeaderFooter.HEADER_EVEN - 1].isEmpty()) @@ -210,7 +210,7 @@ public final class EventBridge implements HDFLowLevelParsingListener _holdParagraph = false; _endHoldIndex = -1; flushHeldParagraph(); - _onHold = new ArrayList(); + _onHold = new ArrayList(); } } @@ -219,7 +219,7 @@ public final class EventBridge implements HDFLowLevelParsingListener CharacterProperties chp = (CharacterProperties)StyleSheet.uncompressProperty(byteChpx, _currentStd.getCHP(), _stsh); - ArrayList textList = BTreeSet.findProperties(start, end, _text.root); + List textList = BTreeSet.findProperties(start, end, _text.root); String text = getTextFromNodes(textList, start, end); _listener.characterRun(chp, text, start - _fcMin, end - _fcMin); @@ -241,7 +241,7 @@ public final class EventBridge implements HDFLowLevelParsingListener } private void flushHeaderProps(int start, int end) { - ArrayList list = BTreeSet.findProperties(start, end, _hdrSections.root); + List list = BTreeSet.findProperties(start, end, _hdrSections.root); int size = list.size(); for (int x = 0; x < size; x++) @@ -253,7 +253,7 @@ public final class EventBridge implements HDFLowLevelParsingListener //SepxNode node = new SepxNode(-1, secStart, secEnd, oldNode.getSepx()); //bodySection(node); - ArrayList parList = BTreeSet.findProperties(secStart, secEnd, _hdrParagraphs.root); + List parList = BTreeSet.findProperties(secStart, secEnd, _hdrParagraphs.root); int parSize = parList.size(); for (int y = 0; y < parSize; y++) @@ -265,7 +265,7 @@ public final class EventBridge implements HDFLowLevelParsingListener PapxNode parNode = new PapxNode(parStart, parEnd, oldParNode.getPapx()); paragraph(parNode); - ArrayList charList = BTreeSet.findProperties(parStart, parEnd, _hdrCharacterRuns.root); + List charList = BTreeSet.findProperties(parStart, parEnd, _hdrCharacterRuns.root); int charSize = charList.size(); for (int z = 0; z < charSize; z++) @@ -282,7 +282,7 @@ public final class EventBridge implements HDFLowLevelParsingListener } } - private String getTextFromNodes(ArrayList list, int start, int end) + private String getTextFromNodes(List list, int start, int end) { int size = list.size(); diff --git a/src/scratchpad/src/org/apache/poi/hdf/extractor/WordDocument.java b/src/scratchpad/src/org/apache/poi/hdf/extractor/WordDocument.java index e8bc31643..ff5330032 100644 --- a/src/scratchpad/src/org/apache/poi/hdf/extractor/WordDocument.java +++ b/src/scratchpad/src/org/apache/poi/hdf/extractor/WordDocument.java @@ -114,6 +114,8 @@ public final class WordDocument { /** * right now this function takes one parameter: a Word file, and outputs an * XSL-FO document at c:\test.xml (this is hardcoded) + * + * @param args The document to read */ public static void main(String args[]) { @@ -175,7 +177,7 @@ public final class WordDocument { } else { - String sText = new String(_header, start, end-start); + String sText = new String(_header, start, end-start, "windows-1252"); out.write(sText); } } @@ -758,7 +760,7 @@ public final class WordDocument { size = lineHeights.size(); for(int x = 0; x < size; x++) { - Integer height = (Integer)lineHeights.get(x); + Integer height = lineHeights.get(x); sum += height.intValue(); } @@ -1765,7 +1767,7 @@ public final class WordDocument { for(int x = 0; x < size; x++) { StringBuffer rowBuffer = tableBodyBuffer; - TableRow row = (TableRow)_table.get(x); + TableRow row = _table.get(x); TAP tap = row.getTAP(); ArrayList cells = row.getCells(); @@ -1797,7 +1799,7 @@ public final class WordDocument { addBorder(rowBuffer, tc._brcBottom, "bottom"); addBorder(rowBuffer, tc._brcRight, "right"); rowBuffer.append(">"); - rowBuffer.append((String)cells.get(y)); + rowBuffer.append(cells.get(y)); rowBuffer.append(""); } rowBuffer.append(""); diff --git a/src/scratchpad/src/org/apache/poi/hdf/model/util/BTreeSet.java b/src/scratchpad/src/org/apache/poi/hdf/model/util/BTreeSet.java index 848e74a80..96cc51d6c 100644 --- a/src/scratchpad/src/org/apache/poi/hdf/model/util/BTreeSet.java +++ b/src/scratchpad/src/org/apache/poi/hdf/model/util/BTreeSet.java @@ -36,14 +36,14 @@ import org.apache.poi.hdf.model.hdftypes.PropertyNode; * */ @Deprecated -public final class BTreeSet extends AbstractSet +public final class BTreeSet extends AbstractSet { /* * Instance Variables */ public BTreeNode root; - private Comparator comparator = null; + private Comparator comparator = null; private int order; int size = 0; @@ -59,7 +59,7 @@ public final class BTreeSet extends AbstractSet this(6); // Default order for a BTreeSet is 32 } - public BTreeSet(Collection c) + public BTreeSet(Collection c) { this(6); // Default order for a BTreeSet is 32 addAll(c); @@ -70,7 +70,7 @@ public final class BTreeSet extends AbstractSet this(order, null); } - public BTreeSet(int order, Comparator comparator) + public BTreeSet(int order, Comparator comparator) { this.order = order; this.comparator = comparator; @@ -81,18 +81,18 @@ public final class BTreeSet extends AbstractSet /* * Public Methods */ - public boolean add(Object x) throws IllegalArgumentException + public boolean add(PropertyNode x) throws IllegalArgumentException { if (x == null) throw new IllegalArgumentException(); return root.insert(x, -1); } - public boolean contains(Object x) + public boolean contains(PropertyNode x) { return root.includes(x); } - public boolean remove(Object x) + public boolean remove(PropertyNode x) { if (x == null) return false; return root.delete(x, -1); @@ -109,14 +109,14 @@ public final class BTreeSet extends AbstractSet size = 0; } - public java.util.Iterator iterator() + public java.util.Iterator iterator() { return new Iterator(); } - public static ArrayList findProperties(int start, int end, BTreeSet.BTreeNode root) + public static List findProperties(int start, int end, BTreeSet.BTreeNode root) { - ArrayList results = new ArrayList(); + List results = new ArrayList(); BTreeSet.Entry[] entries = root.entries; for(int x = 0; x < entries.length; x++) @@ -124,7 +124,7 @@ public final class BTreeSet extends AbstractSet if(entries[x] != null) { BTreeSet.BTreeNode child = entries[x].child; - PropertyNode xNode = (PropertyNode)entries[x].element; + PropertyNode xNode = entries[x].element; if(xNode != null) { int xStart = xNode.getStart(); @@ -135,7 +135,7 @@ public final class BTreeSet extends AbstractSet { if(child != null) { - ArrayList beforeItems = findProperties(start, end, child); + List beforeItems = findProperties(start, end, child); results.addAll(beforeItems); } results.add(xNode); @@ -150,7 +150,7 @@ public final class BTreeSet extends AbstractSet { if(child != null) { - ArrayList beforeItems = findProperties(start, end, child); + List beforeItems = findProperties(start, end, child); results.addAll(beforeItems); } break; @@ -158,7 +158,7 @@ public final class BTreeSet extends AbstractSet } else if(child != null) { - ArrayList afterItems = findProperties(start, end, child); + List afterItems = findProperties(start, end, child); results.addAll(afterItems); } } @@ -172,9 +172,9 @@ public final class BTreeSet extends AbstractSet /* * Private methods */ - int compare(Object x, Object y) + int compare(PropertyNode x, PropertyNode y) { - return (comparator == null ? ((Comparable)x).compareTo(y) : comparator.compare(x, y)); + return (comparator == null ? x.compareTo(y) : comparator.compare(x, y)); } @@ -192,12 +192,12 @@ public final class BTreeSet extends AbstractSet * chance of receiving a NullPointerException. The Iterator.delete method is supported. */ - private class Iterator implements java.util.Iterator + private class Iterator implements java.util.Iterator { private int index = 0; - private Stack parentIndex = new Stack(); // Contains all parentIndicies for currentNode - private Object lastReturned = null; - private Object next; + private Stack parentIndex = new Stack(); // Contains all parentIndicies for currentNode + private PropertyNode lastReturned = null; + private PropertyNode next; private BTreeNode currentNode; Iterator() @@ -211,7 +211,7 @@ public final class BTreeSet extends AbstractSet return next != null; } - public Object next() + public PropertyNode next() { if (next == null) throw new NoSuchElementException(); @@ -241,7 +241,7 @@ public final class BTreeSet extends AbstractSet return temp; } - private Object nextElement() + private PropertyNode nextElement() { if (currentNode.isLeaf()) { @@ -250,13 +250,13 @@ public final class BTreeSet extends AbstractSet else if (!parentIndex.empty()) { //All elements have been returned, return successor of lastReturned if it exists currentNode = currentNode.parent; - index = ((Integer)parentIndex.pop()).intValue(); + index = parentIndex.pop().intValue(); while (index == currentNode.nrElements) { if (parentIndex.empty()) break; currentNode = currentNode.parent; - index = ((Integer)parentIndex.pop()).intValue(); + index = parentIndex.pop().intValue(); } if (index == currentNode.nrElements) return null; //Reached root and he has no more children @@ -289,7 +289,7 @@ public final class BTreeSet extends AbstractSet public static class Entry { - public Object element; + public PropertyNode element; public BTreeNode child; } @@ -309,11 +309,11 @@ public final class BTreeSet extends AbstractSet entries[0] = new Entry(); } - boolean insert(Object x, int parentIndex) + boolean insert(PropertyNode x, int parentIndex) { if (isFull()) { // If full, you must split and promote splitNode before inserting - Object splitNode = entries[nrElements / 2].element; + PropertyNode splitNode = entries[nrElements / 2].element; BTreeNode rightSibling = split(); if (isRoot()) @@ -354,7 +354,7 @@ public final class BTreeSet extends AbstractSet return false; } - boolean includes(Object x) + boolean includes(PropertyNode x) { int index = childToInsertAt(x, true); if (index == -1) return true; @@ -362,7 +362,7 @@ public final class BTreeSet extends AbstractSet return entries[index].child.includes(x); } - boolean delete(Object x, int parentIndex) + boolean delete(PropertyNode x, int parentIndex) { int i = childToInsertAt(x, true); int priorParentIndex = parentIndex; @@ -438,7 +438,7 @@ public final class BTreeSet extends AbstractSet * Creates a new BTreeSet.root which contains only the splitNode and pointers * to it's left and right child. */ - private void splitRoot(Object splitNode, BTreeNode left, BTreeNode right) + private void splitRoot(PropertyNode splitNode, BTreeNode left, BTreeNode right) { BTreeNode newRoot = new BTreeNode(null); newRoot.entries[0].element = splitNode; @@ -450,7 +450,7 @@ public final class BTreeSet extends AbstractSet BTreeSet.this.root = newRoot; } - private void insertSplitNode(Object splitNode, BTreeNode left, BTreeNode right, int insertAt) + private void insertSplitNode(PropertyNode splitNode, BTreeNode left, BTreeNode right, int insertAt) { for (int i = nrElements; i >= insertAt; i--) entries[i + 1] = entries[i]; @@ -462,7 +462,7 @@ public final class BTreeSet extends AbstractSet nrElements++; } - private void insertNewElement(Object x, int insertAt) + private void insertNewElement(PropertyNode x, int insertAt) { for (int i = nrElements; i > insertAt; i--) entries[i] = entries[i - 1]; @@ -482,7 +482,7 @@ public final class BTreeSet extends AbstractSet * element is contained in the calling BTreeNode than the position of the element * in entries[] is returned. */ - private int childToInsertAt(Object x, boolean position) + private int childToInsertAt(PropertyNode x, boolean position) { int index = nrElements / 2; @@ -509,7 +509,7 @@ public final class BTreeSet extends AbstractSet } - private void deleteElement(Object x) + private void deleteElement(PropertyNode x) { int index = childToInsertAt(x, false); for (; index < (nrElements - 1); index++) entries[index] = entries[index + 1]; @@ -568,12 +568,12 @@ public final class BTreeSet extends AbstractSet } } - private void switchWithSuccessor(Object x) + private void switchWithSuccessor(PropertyNode x) { int index = childToInsertAt(x, false); BTreeNode temp = entries[index + 1].child; while (temp.entries[0] != null && temp.entries[0].child != null) temp = temp.entries[0].child; - Object successor = temp.entries[0].element; + PropertyNode successor = temp.entries[0].element; temp.entries[0].element = entries[index].element; entries[index].element = successor; } diff --git a/src/scratchpad/src/org/apache/poi/hdgf/dev/VSDDumper.java b/src/scratchpad/src/org/apache/poi/hdgf/dev/VSDDumper.java index ed5e700d0..40a8a7b31 100644 --- a/src/scratchpad/src/org/apache/poi/hdgf/dev/VSDDumper.java +++ b/src/scratchpad/src/org/apache/poi/hdgf/dev/VSDDumper.java @@ -17,7 +17,7 @@ package org.apache.poi.hdgf.dev; -import java.io.FileInputStream; +import java.io.File; import org.apache.poi.hdgf.HDGFDiagram; import org.apache.poi.hdgf.chunks.Chunk; @@ -26,7 +26,7 @@ import org.apache.poi.hdgf.pointers.Pointer; import org.apache.poi.hdgf.streams.ChunkStream; import org.apache.poi.hdgf.streams.PointerContainingStream; import org.apache.poi.hdgf.streams.Stream; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; /** * Developer helper class to dump out the pointer+stream structure @@ -41,7 +41,7 @@ public final class VSDDumper { } HDGFDiagram hdgf = new HDGFDiagram( - new POIFSFileSystem(new FileInputStream(args[0])) + new NPOIFSFileSystem(new File(args[0])) ); System.out.println("Opened " + args[0]); diff --git a/src/scratchpad/src/org/apache/poi/hdgf/extractor/VisioTextExtractor.java b/src/scratchpad/src/org/apache/poi/hdgf/extractor/VisioTextExtractor.java index 0290d5913..d37a28eb2 100644 --- a/src/scratchpad/src/org/apache/poi/hdgf/extractor/VisioTextExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hdgf/extractor/VisioTextExtractor.java @@ -62,7 +62,7 @@ public final class VisioTextExtractor extends POIOLE2TextExtractor { this(new HDGFDiagram(dir, fs)); } public VisioTextExtractor(InputStream inp) throws IOException { - this(new POIFSFileSystem(inp)); + this(new NPOIFSFileSystem(inp)); } /** diff --git a/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java b/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java index 332a496c6..f591d5a4d 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java @@ -22,6 +22,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import org.apache.poi.hmef.Attachment; import org.apache.poi.hmef.HMEFMessage; @@ -70,13 +71,14 @@ public final class HMEFContentsExtractor { * Extracts the RTF message body to the supplied file */ public void extractMessageBody(File dest) throws IOException { - FileOutputStream fout = new FileOutputStream(dest); - - MAPIRtfAttribute body = (MAPIRtfAttribute) - message.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED); - fout.write(body.getData()); - - fout.close(); + OutputStream fout = new FileOutputStream(dest); + try { + MAPIRtfAttribute body = (MAPIRtfAttribute) + message.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED); + fout.write(body.getData()); + } finally { + fout.close(); + } } /** @@ -101,9 +103,12 @@ public final class HMEFContentsExtractor { // Save it File file = new File(dir, filename); - FileOutputStream fout = new FileOutputStream(file); - fout.write( att.getContents() ); - fout.close(); + OutputStream fout = new FileOutputStream(file); + try { + fout.write( att.getContents() ); + } finally { + fout.close(); + } } } } diff --git a/src/scratchpad/src/org/apache/poi/hpbf/HPBFDocument.java b/src/scratchpad/src/org/apache/poi/hpbf/HPBFDocument.java index 69602e7d8..fb046c803 100644 --- a/src/scratchpad/src/org/apache/poi/hpbf/HPBFDocument.java +++ b/src/scratchpad/src/org/apache/poi/hpbf/HPBFDocument.java @@ -51,18 +51,9 @@ public final class HPBFDocument extends POIDocument { this(fs.getRoot()); } public HPBFDocument(InputStream inp) throws IOException { - this(new POIFSFileSystem(inp)); + this(new NPOIFSFileSystem(inp)); } - /** - * Opens an embedded publisher document, - * at the given directory. - * @deprecated Use {@link #HPBFDocument(DirectoryNode)} instead - */ - @Deprecated - public HPBFDocument(DirectoryNode dir, POIFSFileSystem fs) throws IOException { - this(dir); - } /** * Opens an embedded publisher document, * at the given directory. diff --git a/src/scratchpad/src/org/apache/poi/hpbf/dev/HPBFDumper.java b/src/scratchpad/src/org/apache/poi/hpbf/dev/HPBFDumper.java index df4bb15a4..3ea5e9a35 100644 --- a/src/scratchpad/src/org/apache/poi/hpbf/dev/HPBFDumper.java +++ b/src/scratchpad/src/org/apache/poi/hpbf/dev/HPBFDumper.java @@ -25,7 +25,7 @@ import org.apache.poi.ddf.DefaultEscherRecordFactory; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentEntry; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.StringUtil; @@ -35,12 +35,12 @@ import org.apache.poi.util.StringUtil; * constructed. */ public final class HPBFDumper { - private POIFSFileSystem fs; - public HPBFDumper(POIFSFileSystem fs) { + private NPOIFSFileSystem fs; + public HPBFDumper(NPOIFSFileSystem fs) { this.fs = fs; } public HPBFDumper(InputStream inp) throws IOException { - this(new POIFSFileSystem(inp)); + this(new NPOIFSFileSystem(inp)); } private static byte[] getData(DirectoryNode dir, String name) throws IOException { diff --git a/src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java b/src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java index c6bfca93b..7625a08b8 100644 --- a/src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java +++ b/src/scratchpad/src/org/apache/poi/hpbf/dev/PLCDumper.java @@ -24,7 +24,7 @@ import java.io.InputStream; import org.apache.poi.hpbf.HPBFDocument; import org.apache.poi.hpbf.model.QuillContents; import org.apache.poi.hpbf.model.qcbits.QCBit; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.util.HexDump; /** @@ -40,11 +40,11 @@ public final class PLCDumper { doc = hpbfDoc; qc = doc.getQuillContents(); } - public PLCDumper(POIFSFileSystem fs) throws IOException { + public PLCDumper(NPOIFSFileSystem fs) throws IOException { this(new HPBFDocument(fs)); } public PLCDumper(InputStream inp) throws IOException { - this(new POIFSFileSystem(inp)); + this(new NPOIFSFileSystem(inp)); } public static void main(String[] args) throws Exception { diff --git a/src/scratchpad/src/org/apache/poi/hpbf/extractor/PublisherTextExtractor.java b/src/scratchpad/src/org/apache/poi/hpbf/extractor/PublisherTextExtractor.java index be238b6f3..2295f235f 100644 --- a/src/scratchpad/src/org/apache/poi/hpbf/extractor/PublisherTextExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hpbf/extractor/PublisherTextExtractor.java @@ -53,10 +53,6 @@ public final class PublisherTextExtractor extends POIOLE2TextExtractor { public PublisherTextExtractor(InputStream is) throws IOException { this(new POIFSFileSystem(is)); } - @Deprecated - public PublisherTextExtractor(DirectoryNode dir, POIFSFileSystem fs) throws IOException { - this(new HPBFDocument(dir, fs)); - } /** * Should a call to getText() return hyperlinks inline diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java b/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java index 4c9e9ceaf..9755d46d2 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java @@ -32,15 +32,18 @@ public abstract class Bitmap extends HSLFPictureData { public byte[] getData(){ byte[] rawdata = getRawData(); - byte[] imgdata = new byte[rawdata.length-17]; - System.arraycopy(rawdata, 17, imgdata, 0, imgdata.length); + int prefixLen = 16*uidInstanceCount+1; + byte[] imgdata = new byte[rawdata.length-prefixLen]; + System.arraycopy(rawdata, prefixLen, imgdata, 0, imgdata.length); return imgdata; } public void setData(byte[] data) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] checksum = getChecksum(data); - out.write(checksum); + for (int i=0; i0x7A80 + * DIB signature is {@code 0x7A80} or {@code 0x7A90} * - * @return DIB signature (0x7A80) + * @return DIB signature ({@code 0x7A80} or {@code 0x7A90}) */ public int getSignature(){ - return 0x7A80; + return (uidInstanceCount == 1 ? 0x7A80 : 0x7A90); } + + /** + * Sets the DIB signature - either {@code 0x7A80} or {@code 0x7A90} + */ + public void setSignature(int signature) { + switch (signature) { + case 0x7A80: + uidInstanceCount = 1; + break; + case 0x7A90: + uidInstanceCount = 2; + break; + default: + throw new IllegalArgumentException(signature+" is not a valid instance/signature value for DIB"); + } + } public byte[] getData(){ return addBMPHeader ( super.getData() ); diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java b/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java index d7dadb6c5..5d3a45e65 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java @@ -84,12 +84,28 @@ public final class EMF extends Metafile { } /** - * EMF signature is 0x3D40 + * EMF signature is {@code 0x3D40} or {@code 0x3D50} * - * @return EMF signature (0x3D40) + * @return EMF signature ({@code 0x3D40} or {@code 0x3D50}) */ public int getSignature(){ - return 0x3D40; + return (uidInstanceCount == 1 ? 0x3D40 : 0x3D50); + } + + /** + * Sets the EMF signature - either {@code 0x3D40} or {@code 0x3D50} + */ + public void setSignature(int signature) { + switch (signature) { + case 0x3D40: + uidInstanceCount = 1; + break; + case 0x3D50: + uidInstanceCount = 2; + break; + default: + throw new IllegalArgumentException(signature+" is not a valid instance/signature value for EMF"); + } } public String getContentType() { diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java b/src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java index 08ba5ceb9..ed436beb2 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java @@ -26,6 +26,10 @@ import org.apache.poi.hslf.usermodel.HSLFPictureShape; */ public final class JPEG extends Bitmap { + public enum ColorSpace { rgb, cymk }; + + private ColorSpace colorSpace = ColorSpace.rgb; + /** * @return type of this picture * @see org.apache.poi.hslf.usermodel.HSLFPictureShape#JPEG @@ -34,13 +38,49 @@ public final class JPEG extends Bitmap { return HSLFPictureShape.JPEG; } + public ColorSpace getColorSpace() { + return colorSpace; + } + + public void setColorSpace(ColorSpace colorSpace) { + this.colorSpace = colorSpace; + } + /** - * JPEG signature is 0x46A0 + * JPEG signature is one of {@code 0x46A0, 0x46B0, 0x6E20, 0x6E30} * - * @return JPEG signature (0x46A0) + * @return JPEG signature ({@code 0x46A0, 0x46B0, 0x6E20, 0x6E30}) */ public int getSignature(){ - return 0x46A0; + return (colorSpace == ColorSpace.rgb) + ? (uidInstanceCount == 1 ? 0x46A0 : 0x46B0) + : (uidInstanceCount == 1 ? 0x6E20 : 0x6E30); + } + + /** + * Sets the PICT signature - either {@code 0x5420} or {@code 0x5430} + */ + public void setSignature(int signature) { + switch (signature) { + case 0x46A0: + uidInstanceCount = 1; + colorSpace = ColorSpace.rgb; + break; + case 0x46B0: + uidInstanceCount = 2; + colorSpace = ColorSpace.rgb; + break; + case 0x6E20: + uidInstanceCount = 1; + colorSpace = ColorSpace.cymk; + break; + case 0x6E30: + uidInstanceCount = 2; + colorSpace = ColorSpace.cymk; + break; + default: + throw new IllegalArgumentException(signature+" is not a valid instance/signature value for JPEG"); + } } public String getContentType() { diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java b/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java index 535e20641..b9f66ff29 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java @@ -86,8 +86,8 @@ public abstract class Metafile extends HSLFPictureData { zipsize = LittleEndian.getInt(data, pos); pos += LittleEndian.INT_SIZE; - compression = LittleEndian.getUnsignedByte(data, pos); pos++; - filter = LittleEndian.getUnsignedByte(data, pos); pos++; + compression = LittleEndian.getUByte(data, pos); pos++; + filter = LittleEndian.getUByte(data, pos); pos++; } public void write(OutputStream out) throws IOException { diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java b/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java index 016c50f87..bebbcf450 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java @@ -33,10 +33,6 @@ import org.apache.poi.hslf.usermodel.HSLFShape; */ public final class PICT extends Metafile { - public PICT(){ - super(); - } - /** * Extract compressed PICT data from a ppt */ @@ -46,7 +42,7 @@ public final class PICT extends Metafile { byte[] macheader = new byte[512]; ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(macheader); - int pos = CHECKSUM_SIZE; + int pos = CHECKSUM_SIZE*uidInstanceCount; byte[] pict; try { pict = read(rawdata, pos); @@ -109,12 +105,28 @@ public final class PICT extends Metafile { } /** - * PICT signature is 0x5430 + * PICT signature is {@code 0x5420} or {@code 0x5430} * - * @return PICT signature (0x5430) + * @return PICT signature ({@code 0x5420} or {@code 0x5430}) */ public int getSignature(){ - return 0x5430; + return (uidInstanceCount == 1 ? 0x5420 : 0x5430); + } + + /** + * Sets the PICT signature - either {@code 0x5420} or {@code 0x5430} + */ + public void setSignature(int signature) { + switch (signature) { + case 0x5420: + uidInstanceCount = 1; + break; + case 0x5430: + uidInstanceCount = 2; + break; + default: + throw new IllegalArgumentException(signature+" is not a valid instance/signature value for PICT"); + } } public String getContentType() { diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java b/src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java index 114b736bf..cd61a9bd6 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java @@ -53,12 +53,28 @@ public final class PNG extends Bitmap { } /** - * PNG signature is 0x6E00 + * PNG signature is {@code 0x6E00} or {@code 0x6E10} * - * @return PNG signature (0x6E00) + * @return PNG signature ({@code 0x6E00} or {@code 0x6E10}) */ public int getSignature(){ - return 0x6E00; + return (uidInstanceCount == 1 ? 0x6E00 : 0x6E10); + } + + /** + * Sets the PNG signature - either {@code 0x6E00} or {@code 0x6E10} + */ + public void setSignature(int signature) { + switch (signature) { + case 0x6E00: + uidInstanceCount = 1; + break; + case 0x6E10: + uidInstanceCount = 2; + break; + default: + throw new IllegalArgumentException(signature+" is not a valid instance/signature value for PNG"); + } } public String getContentType() { diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java b/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java index a84aed2e6..e4f3b3914 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java @@ -43,8 +43,8 @@ public final class WMF extends Metafile { ByteArrayOutputStream out = new ByteArrayOutputStream(); InputStream is = new ByteArrayInputStream( rawdata ); Header header = new Header(); - header.read(rawdata, CHECKSUM_SIZE); - is.skip(header.getSize() + CHECKSUM_SIZE); + header.read(rawdata, CHECKSUM_SIZE*uidInstanceCount); + is.skip(header.getSize() + CHECKSUM_SIZE*uidInstanceCount); AldusHeader aldus = new AldusHeader(); aldus.left = header.bounds.x; @@ -84,7 +84,9 @@ public final class WMF extends Metafile { byte[] checksum = getChecksum(data); ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write(checksum); + for (int i=0; i0x2160 + * WMF signature is either {@code 0x2160} or {@code 0x2170} */ public int getSignature(){ - return 0x2160; + return (uidInstanceCount == 1 ? 0x2160 : 0x2170); } + /** + * Sets the WMF signature - either {@code 0x2160} or {@code 0x2170} + */ + public void setSignature(int signature) { + switch (signature) { + case 0x2160: + uidInstanceCount = 1; + break; + case 0x2170: + uidInstanceCount = 2; + break; + default: + throw new IllegalArgumentException(signature+" is not a valid instance/signature value for WMF"); + } + } /** * Aldus Placeable Metafile header - 22 byte structure before WMF data. diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java b/src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java index 0b5755261..dad74ffa6 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/PPTXMLDump.java @@ -18,7 +18,6 @@ package org.apache.poi.hslf.dev; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; @@ -28,7 +27,7 @@ import java.io.Writer; import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.util.LittleEndian; /** @@ -50,9 +49,7 @@ public final class PPTXMLDump { protected boolean hexHeader = true; public PPTXMLDump(File ppt) throws IOException { - FileInputStream fis = new FileInputStream(ppt); - POIFSFileSystem fs = new POIFSFileSystem(fis); - fis.close(); + NPOIFSFileSystem fs = new NPOIFSFileSystem(ppt); //read the document entry from OLE file system DocumentEntry entry = (DocumentEntry)fs.getRoot().getEntry(PPDOC_ENTRY); diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowDumper.java b/src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowDumper.java index 3954f6b48..e098d4083 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowDumper.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowDumper.java @@ -17,11 +17,17 @@ package org.apache.poi.hslf.dev; -import java.io.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ddf.DefaultEscherRecordFactory; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.poifs.filesystem.DocumentEntry; -import org.apache.poi.ddf.*; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.hslf.record.HSLFEscherRecordFactory; import org.apache.poi.hslf.record.RecordTypes; import org.apache.poi.util.LittleEndian; @@ -37,12 +43,9 @@ import org.apache.poi.util.LittleEndian; * To peek inside PPDrawings, which hold Escher drawings, we use the * DDF package from POI (but we can fake it by using the Escher listings * from hslf.record.RecordTypes also) - * - * @author Nick Burch */ public final class SlideShowDumper { - private InputStream istream; - private POIFSFileSystem filesystem; + private NPOIFSFileSystem filesystem; private byte[] _docstream; @@ -91,7 +94,7 @@ public final class SlideShowDumper { */ public SlideShowDumper(String fileName) throws IOException { - this(new FileInputStream(fileName)); + this(new NPOIFSFileSystem(new File(fileName))); } /** @@ -104,8 +107,7 @@ public final class SlideShowDumper { public SlideShowDumper(InputStream inputStream) throws IOException { //do Ole stuff - this(new POIFSFileSystem(inputStream)); - istream = inputStream; + this(new NPOIFSFileSystem(inputStream)); } /** @@ -115,7 +117,7 @@ public final class SlideShowDumper { * @param filesystem the POIFS FileSystem to read from * @throws IOException if there is a problem while parsing the document. */ - public SlideShowDumper(POIFSFileSystem filesystem) throws IOException + public SlideShowDumper(NPOIFSFileSystem filesystem) throws IOException { this.filesystem = filesystem; @@ -152,10 +154,7 @@ public final class SlideShowDumper { */ public void close() throws IOException { - if(istream != null) { - istream.close(); - } - filesystem = null; + filesystem.close(); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java b/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java index 190ad0a41..e3beebf4b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java @@ -77,7 +77,7 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { * @param fileName The name of the file to extract from */ public PowerPointExtractor(String fileName) throws IOException { - this(new FileInputStream(fileName)); + this(new NPOIFSFileSystem(new File(fileName))); } /** diff --git a/src/scratchpad/src/org/apache/poi/hslf/extractor/QuickButCruddyTextExtractor.java b/src/scratchpad/src/org/apache/poi/hslf/extractor/QuickButCruddyTextExtractor.java index 260eebd60..8396ae123 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/extractor/QuickButCruddyTextExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hslf/extractor/QuickButCruddyTextExtractor.java @@ -18,6 +18,9 @@ package org.apache.poi.hslf.extractor; import java.io.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; @@ -25,7 +28,7 @@ import org.apache.poi.hslf.record.*; import org.apache.poi.hslf.usermodel.HSLFTextParagraph; import org.apache.poi.hslf.usermodel.HSLFTextShape; import org.apache.poi.poifs.filesystem.DocumentEntry; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.util.LittleEndian; /** @@ -45,11 +48,9 @@ import org.apache.poi.util.LittleEndian; * Almost everyone will want to use @see PowerPointExtractor instead. There * are only a very small number of cases (eg some performance sensitive * lucene indexers) that would ever want to use this! - * - * @author Nick Burch */ public final class QuickButCruddyTextExtractor { - private POIFSFileSystem fs; + private NPOIFSFileSystem fs; private InputStream is; private byte[] pptContents; @@ -77,7 +78,7 @@ public final class QuickButCruddyTextExtractor { * @param fileName */ public QuickButCruddyTextExtractor(String fileName) throws IOException { - this(new FileInputStream(fileName)); + this(new NPOIFSFileSystem(new File(fileName))); } /** @@ -85,7 +86,7 @@ public final class QuickButCruddyTextExtractor { * @param iStream */ public QuickButCruddyTextExtractor(InputStream iStream) throws IOException { - this(new POIFSFileSystem(iStream)); + this(new NPOIFSFileSystem(iStream)); is = iStream; } @@ -93,7 +94,7 @@ public final class QuickButCruddyTextExtractor { * Creates an extractor from a POIFS Filesystem * @param poifs */ - public QuickButCruddyTextExtractor(POIFSFileSystem poifs) throws IOException { + public QuickButCruddyTextExtractor(NPOIFSFileSystem poifs) throws IOException { fs = poifs; // Find the PowerPoint bit, and get out the bytes diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java index 0ed4357ee..e34103a8c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java @@ -30,21 +30,18 @@ import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; import org.apache.poi.hslf.exceptions.OldPowerPointFormatException; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentEntry; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.StringUtil; - /** - * This is a special kind of Atom, becauase it doesn't live inside the - * PowerPoint document. Instead, it lives in a seperate stream in the - * document. As such, it has to be treaded specially - * - * @author Nick Burch + * This is a special kind of Atom, because it doesn't live inside the + * PowerPoint document. Instead, it lives in a separate stream in the + * document. As such, it has to be treated specially */ - public class CurrentUserAtom { private static POILogger logger = POILogFactory.getLogger(CurrentUserAtom.class); @@ -117,6 +114,7 @@ public class CurrentUserAtom /** * Find the Current User in the filesystem, and create from that + * @deprecated Use {@link #CurrentUserAtom(DirectoryNode)} instead */ public CurrentUserAtom(POIFSFileSystem fs) throws IOException { this(fs.getRoot()); @@ -278,7 +276,7 @@ public class CurrentUserAtom /** * Writes ourselves back out to a filesystem */ - public void writeToFS(POIFSFileSystem fs) throws IOException { + public void writeToFS(NPOIFSFileSystem fs) throws IOException { // Grab contents ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeOut(baos); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java index 230a6401d..aa7e8a32e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java @@ -50,6 +50,11 @@ public abstract class HSLFPictureData implements PictureData { */ protected int offset; + /** + * The instance type/signatures defines if one or two UID instances will be included + */ + protected int uidInstanceCount = 1; + /** * Returns type of this picture. * Must be one of the static constants defined in the Picture class. @@ -82,6 +87,15 @@ public abstract class HSLFPictureData implements PictureData { */ protected abstract int getSignature(); + public abstract void setSignature(int signature); + + /** + * The instance type/signatures defines if one or two UID instances will be included + */ + protected int getUIDInstanceCount() { + return uidInstanceCount; + } + /** * Returns the raw binary data of this Picture excluding the first 8 bytes * which hold image signature and size of the image data. diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java index 9288052c6..2ecb7efe9 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java @@ -184,11 +184,12 @@ public abstract class HSLFShape implements Shape { h = clientRec.getRow1()-clientRec.getCol1(); } + // TODO: find out where this -1 value comes from at #57820 (link to ms docs?) Rectangle2D anchor = new Rectangle2D.Float( - (float)Units.masterToPoints(x), - (float)Units.masterToPoints(y), - (float)Units.masterToPoints(w), - (float)Units.masterToPoints(h) + (float)(x == -1 ? -1 : Units.masterToPoints(x)), + (float)(y == -1 ? -1 : Units.masterToPoints(y)), + (float)(w == -1 ? -1 : Units.masterToPoints(w)), + (float)(h == -1 ? -1 : Units.masterToPoints(h)) ); return anchor; diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java index ec5f735d1..34638f630 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java @@ -83,14 +83,6 @@ public final class HSLFSlideShowImpl extends POIDocument { // Embedded objects stored in storage records in the document stream, lazily populated. private HSLFObjectData[] _objects; - /** - * Returns the underlying POIFSFileSystem for the document - * that is open. - */ - protected POIFSFileSystem getPOIFSFileSystem() { - return directory.getFileSystem(); - } - /** * Returns the directory in the underlying POIFSFileSystem for the * document that is open. diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java index 29fdee2dc..d9f5b11eb 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java @@ -178,7 +178,7 @@ public final class HSLFTable extends HSLFGroupShape implements TableShape { } }); - int y0 = -1; + int y0 = (shapeList.isEmpty()) ? -1 : shapeList.get(0).getAnchor().y - 1; int maxrowlen = 0; List> lst = new ArrayList>(); List row = null; diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java index c8867a6c7..dd9ab9a5f 100644 --- a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java @@ -69,15 +69,28 @@ public class MessageSubmissionChunk extends Chunk { for(String part : parts) { if(part.startsWith("l=")) { // Format of this bit appears to be l=-

    see [MS-DOC], v20140721, 2.9.150

    + * + * @return the first ({@code 0} is the most significant) level after which + * the numbering does not restart or {@code -1} if no restart is applicable + */ + public short getRestart() { + return _lvlf.isFNoRestart() ? _lvlf.getIlvlRestartLim() : -1; + } + + /** + * Determines if the number formatting shall be overridden by + * {@code msonfcArabic}; unless it originally was {@code msonfcArabicLZ} + * in which case it is preserved. + *

    see [MS-DOC], v20140721, 2.9.150 and [MS-OSHARED], v20140721, 2.2.1.3

    + * + * @return {@code true} if the level numbering of this and all more + * significant levels must be overridden; {@code false} otherwise + */ + public boolean isLegalNumbering() { + return _lvlf.isFLegal(); + } + + /** + * Array which specifies the character offsets of the level numbers in a + * level numbering string. + *

    see [MS-DOC], v20140721, 2.9.150

    + * + * @return {@code 0}-terminated array, unless it is full + */ + public byte[] getLevelNumberingPlaceholderOffsets() { + return _lvlf.getRgbxchNums(); + } + int read( final byte[] data, final int startOffset ) { int offset = startOffset; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/model/SectionTable.java b/src/scratchpad/src/org/apache/poi/hwpf/model/SectionTable.java index 5414c2797..956b1b962 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/model/SectionTable.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/model/SectionTable.java @@ -38,11 +38,11 @@ public class SectionTable private final static POILogger _logger = POILogFactory.getLogger(SectionTable.class); private static final int SED_SIZE = 12; - protected ArrayList _sections = new ArrayList(); + protected List _sections = new ArrayList(); protected List _text; /** So we can know if things are unicode or not */ - private TextPieceTable tpt; + //private TextPieceTable tpt; public SectionTable() { @@ -54,7 +54,7 @@ public class SectionTable TextPieceTable tpt, int mainLength) { PlexOfCps sedPlex = new PlexOfCps(tableStream, offset, size, SED_SIZE); - this.tpt = tpt; + //this.tpt = tpt; this._text = tpt.getTextPieces(); int length = sedPlex.length(); @@ -160,7 +160,7 @@ public class SectionTable // return FC; // } - public ArrayList getSections() + public List getSections() { return _sections; } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterProperties.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterProperties.java index fd6d631c7..3c5e25fb6 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterProperties.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterProperties.java @@ -382,7 +382,7 @@ public final class CharacterProperties cp.setDttmPropRMark( (DateAndTime) getDttmPropRMark().clone() ); cp.setDttmDispFldRMark( (DateAndTime) getDttmDispFldRMark().clone() ); cp.setXstDispFldRMark( getXstDispFldRMark().clone() ); - cp.setShd( (ShadingDescriptor) getShd().clone() ); + cp.setShd( getShd().clone() ); cp.setBrc( (BorderCode) getBrc().clone() ); return cp; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterRun.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterRun.java index d02f8ae9b..4181c197f 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterRun.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/CharacterRun.java @@ -570,7 +570,7 @@ public final class CharacterRun extends Range cp._props.setDttmDispFldRMark((DateAndTime)_props.getDttmDispFldRMark(). clone()); cp._props.setXstDispFldRMark(_props.getXstDispFldRMark().clone()); - cp._props.setShd((ShadingDescriptor)_props.getShd().clone()); + cp._props.setShd(_props.getShd().clone()); return cp; } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java index 41bcb9652..6f69f7172 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/HWPFList.java @@ -17,10 +17,6 @@ package org.apache.poi.hwpf.usermodel; -import org.apache.poi.util.POILogFactory; - -import org.apache.poi.util.POILogger; - import org.apache.poi.hwpf.model.ListTables; import org.apache.poi.util.Internal; @@ -52,7 +48,7 @@ import org.apache.poi.hwpf.sprm.ParagraphSprmCompressor; */ public final class HWPFList { - private static POILogger log = POILogFactory.getLogger( HWPFList.class ); + //private static POILogger log = POILogFactory.getLogger( HWPFList.class ); private boolean _ignoreLogicalLeftIdentation = false; private LFO _lfo; diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/ParagraphProperties.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/ParagraphProperties.java index 7583b5904..1dbeae4f8 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/ParagraphProperties.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/ParagraphProperties.java @@ -43,7 +43,7 @@ public final class ParagraphProperties extends PAPAbstractType implements pp.setBrcBar( (BorderCode) getBrcBar().clone() ); pp.setDcs( getDcs().clone() ); pp.setLspd( (LineSpacingDescriptor) getLspd().clone() ); - pp.setShd( (ShadingDescriptor) getShd().clone() ); + pp.setShd( getShd().clone() ); pp.setPhe( getPhe().clone() ); return pp; } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/TableCellDescriptor.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/TableCellDescriptor.java index 812e3b661..4d01ec891 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/TableCellDescriptor.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/TableCellDescriptor.java @@ -53,7 +53,7 @@ public final class TableCellDescriptor extends TCAbstractType implements throws CloneNotSupportedException { TableCellDescriptor tc = (TableCellDescriptor)super.clone(); - tc.setShd( (ShadingDescriptor) getShd().clone() ); + tc.setShd( getShd().clone() ); tc.setBrcTop((BorderCode)getBrcTop().clone()); tc.setBrcLeft((BorderCode)getBrcLeft().clone()); tc.setBrcBottom((BorderCode)getBrcBottom().clone()); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/TableProperties.java b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/TableProperties.java index 31c3d974e..001b3cfb2 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/usermodel/TableProperties.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/usermodel/TableProperties.java @@ -71,7 +71,7 @@ public final class TableProperties extends TAPAbstractType implements Cloneable tap.setRgshd( new ShadingDescriptor[getRgshd().length] ); for ( int x = 0; x < getRgshd().length; x++ ) { - tap.getRgshd()[x] = (ShadingDescriptor) getRgshd()[x].clone(); + tap.getRgshd()[x] = getRgshd()[x].clone(); } tap.setBrcBottom( (BorderCode) getBrcBottom().clone() ); @@ -81,7 +81,7 @@ public final class TableProperties extends TAPAbstractType implements Cloneable tap.setBrcTop( (BorderCode) getBrcTop().clone() ); tap.setBrcVertical( (BorderCode) getBrcVertical().clone() ); - tap.setShdTable( (ShadingDescriptor) getShdTable().clone() ); + tap.setShdTable( getShdTable().clone() ); tap.setRgbrcInsideDefault_0( (BorderCode) getRgbrcInsideDefault_0() .clone() ); diff --git a/src/scratchpad/testcases/org/apache/poi/TestPOIDocumentScratchpad.java b/src/scratchpad/testcases/org/apache/poi/TestPOIDocumentScratchpad.java index 652314c20..30296cf82 100644 --- a/src/scratchpad/testcases/org/apache/poi/TestPOIDocumentScratchpad.java +++ b/src/scratchpad/testcases/org/apache/poi/TestPOIDocumentScratchpad.java @@ -75,7 +75,7 @@ public final class TestPOIDocumentScratchpad extends TestCase { public void testWriteProperties() throws Exception { // Just check we can write them back out into a filesystem - POIFSFileSystem outFS = new POIFSFileSystem(); + NPOIFSFileSystem outFS = new NPOIFSFileSystem(); doc.writeProperties(outFS); // Should now hold them @@ -87,7 +87,7 @@ public final class TestPOIDocumentScratchpad extends TestCase { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Write them out - POIFSFileSystem outFS = new POIFSFileSystem(); + NPOIFSFileSystem outFS = new NPOIFSFileSystem(); doc.writeProperties(outFS); outFS.writeFilesystem(baos); diff --git a/src/scratchpad/testcases/org/apache/poi/hdf/extractor/TestWordDocument.java b/src/scratchpad/testcases/org/apache/poi/hdf/extractor/TestWordDocument.java index 1cf29f437..f0941674f 100644 --- a/src/scratchpad/testcases/org/apache/poi/hdf/extractor/TestWordDocument.java +++ b/src/scratchpad/testcases/org/apache/poi/hdf/extractor/TestWordDocument.java @@ -17,6 +17,15 @@ package org.apache.poi.hdf.extractor; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.poi.hwpf.HWPFDocument; +import org.apache.poi.hwpf.HWPFTestDataSamples; +import org.apache.poi.hwpf.extractor.WordExtractor; import org.junit.Test; @@ -31,4 +40,31 @@ public class TestWordDocument { //WordDocument.main(new String[] {"test-data/document/Word6.doc", "/tmp/test.doc"}); WordDocument.main(new String[] {"test-data/document/53446.doc", "/tmp/test.doc"}); } + + @SuppressWarnings("deprecation") + @Test + public void test47304() throws IOException { + HWPFDocument doc = HWPFTestDataSamples.openSampleFile("47304.doc"); + assertNotNull(doc); + + WordExtractor extractor = new WordExtractor(doc); + String text = extractor.getText(); + //System.out.println(text); + assertTrue("Had: " + text, text.contains("Just a \u201Ctest\u201D")); + extractor.close(); + + WordDocument wordDoc = new WordDocument("test-data/document/47304.doc"); + + StringWriter docTextWriter = new StringWriter(); + PrintWriter out = new PrintWriter(docTextWriter); + try { + wordDoc.writeAllText(out); + } finally { + out.close(); + } + docTextWriter.close(); + + //System.out.println(docTextWriter.toString()); + assertTrue("Had: " + docTextWriter.toString(), docTextWriter.toString().contains("Just a \u201Ctest\u201D")); + } } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java index 3337d58c3..fb49dbb1c 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java @@ -17,14 +17,27 @@ package org.apache.poi.hslf.model; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.List; +import org.apache.poi.POIDataSamples; import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.usermodel.*; +import org.apache.poi.hslf.usermodel.HSLFShape; +import org.apache.poi.hslf.usermodel.HSLFSlide; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFTable; +import org.apache.poi.hslf.usermodel.HSLFTableCell; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.sl.usermodel.TableShape; import org.junit.Test; /** @@ -33,6 +46,7 @@ import org.junit.Test; * @author Yegor Kozlov */ public final class TestTable { + private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); /** * Test that ShapeFactory works properly and returns Table @@ -105,4 +119,31 @@ public final class TestTable { } } + + /** + * Bug 57820: initTable throws NullPointerException + * when the table is positioned with its top at -1 + */ + @Test + public void test57820() throws Exception { + SlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("bug57820-initTableNullRefrenceException.ppt")); + + List> slides = ppt.getSlides(); + assertEquals(1, slides.size()); + + List shapes = slides.get(0).getShapes(); //throws NullPointerException + + TableShape tbl = null; + for(Shape s : shapes) { + if(s instanceof TableShape) { + tbl = (TableShape)s; + break; + } + } + + assertNotNull(tbl); + + // handling changed in common sl, so it evaluates to 0 now + assertEquals(0, tbl.getAnchor().getY(), 0); + } } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java index 14200d501..5ede8b094 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java @@ -34,6 +34,7 @@ import org.apache.poi.sl.draw.Drawable; import org.apache.poi.sl.usermodel.Slide; import org.apache.poi.sl.usermodel.SlideShow; import org.apache.poi.util.JvmBugs; +import org.junit.Ignore; import org.junit.Test; /** @@ -138,7 +139,7 @@ public final class TestPicture { } @Test - // @Ignore("Just for visual validation - antialiasing is different on various systems") + @Ignore("Just for visual validation - antialiasing is different on various systems") public void bug54541() throws Exception { String files[] = { // "sample_pptx_grouping_issues.pptx", diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java index 8ad3ba6d7..ce49cd55d 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java @@ -413,10 +413,6 @@ public final class TestRichTextRun { fs.close(); byte[] raw_ss = baos.toByteArray(); - FileOutputStream fos = new FileOutputStream("PowerPoint Document.new.stream"); - fos.write(raw_ss); - fos.close(); - // different paragraph mask, because of sanitizing raw_ss[169030] = 0x0a; diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/AllHSMFTests.java b/src/scratchpad/testcases/org/apache/poi/hsmf/AllHSMFTests.java index 710d991d9..7664bddec 100644 --- a/src/scratchpad/testcases/org/apache/poi/hsmf/AllHSMFTests.java +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/AllHSMFTests.java @@ -27,19 +27,19 @@ import org.apache.poi.hsmf.parsers.*; public final class AllHSMFTests { public static Test suite() { TestSuite suite = new TestSuite(AllHSMFTests.class.getName()); + suite.addTestSuite(TestBasics.class); suite.addTestSuite(TestBlankFileRead.class); suite.addTestSuite(TestSimpleFileRead.class); suite.addTestSuite(TestOutlook30FileRead.class); suite.addTestSuite(TestFileWithAttachmentsRead.class); - suite.addTestSuite(TestChunkData.class); suite.addTestSuite(TestTypes.class); suite.addTestSuite(TestSorters.class); - suite.addTestSuite(TestOutlookTextExtractor.class); - suite.addTestSuite(TestPOIFSChunkParser.class); + suite.addTestSuite(TestMessageSubmissionChunkY2KRead.class); + suite.addTestSuite(TestMessageSubmissionChunk.class); return suite; } diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunk.java b/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunk.java new file mode 100644 index 000000000..0cbad21b9 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunk.java @@ -0,0 +1,58 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hsmf; + +import java.io.IOException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.POIDataSamples; + +import java.util.Calendar; + +import junit.framework.TestCase; + +public final class TestMessageSubmissionChunk extends TestCase { + + private MAPIMessage mapiMessageExtraHyphenSubmissionChunk; + private MAPIMessage mapiMessageNormalSubmissionChunk; + + /** + * Initialise this test, load up the test messages. + * @throws Exception + */ + public TestMessageSubmissionChunk() throws IOException { + POIDataSamples samples = POIDataSamples.getHSMFInstance(); + this.mapiMessageExtraHyphenSubmissionChunk = new MAPIMessage(samples.openResourceAsStream("message_extra_hyphen_submission_chunk.msg")); + this.mapiMessageNormalSubmissionChunk = new MAPIMessage(samples.openResourceAsStream("message_normal_submission_chunk.msg")); + } + + public void testReadMessageDateExtraHyphenSubmissionChunk() throws ChunkNotFoundException { + final Calendar date = mapiMessageExtraHyphenSubmissionChunk.getMessageDate(); + TestCase.assertNotNull(date); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(2007, year); + } + + public void testReadMessageDateNormalSubmissionChunk() throws ChunkNotFoundException { + final Calendar date = mapiMessageNormalSubmissionChunk.getMessageDate(); + TestCase.assertNotNull(date); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(2007, year); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunkY2KRead.java b/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunkY2KRead.java new file mode 100644 index 000000000..c10ba0b65 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/TestMessageSubmissionChunkY2KRead.java @@ -0,0 +1,67 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hsmf; + +import java.io.IOException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.POIDataSamples; + +import java.util.Calendar; + +import junit.framework.TestCase; + +public final class TestMessageSubmissionChunkY2KRead extends TestCase { + + private MAPIMessage mapiMessage1979; + private MAPIMessage mapiMessage1980; + private MAPIMessage mapiMessage1981; + + /** + * Initialise this test, load up the three test messages. + * @throws Exception + */ + public TestMessageSubmissionChunkY2KRead() throws IOException { + POIDataSamples samples = POIDataSamples.getHSMFInstance(); + this.mapiMessage1979 = new MAPIMessage(samples.openResourceAsStream("message_1979.msg")); + this.mapiMessage1980 = new MAPIMessage(samples.openResourceAsStream("message_1980.msg")); + this.mapiMessage1981 = new MAPIMessage(samples.openResourceAsStream("message_1981.msg")); + } + + // 1979 is one year before our pivot year (so this is an expected "failure") + public void testReadMessageDate1979() throws ChunkNotFoundException { + final Calendar date = mapiMessage1979.getMessageDate(); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(2079, year); + } + + // 1980 is our pivot year (so this is an expected "failure") + public void testReadMessageDate1980() throws ChunkNotFoundException { + final Calendar date = mapiMessage1980.getMessageDate(); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(2080, year); + } + + // 1981 is one year after our pivot year (so this starts working) + public void testReadMessageDate1981() throws ChunkNotFoundException { + final Calendar date = mapiMessage1981.getMessageDate(); + final int year = date.get(Calendar.YEAR); + TestCase.assertEquals(1981, year); + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/extractor/TestOutlookTextExtractor.java b/src/scratchpad/testcases/org/apache/poi/hsmf/extractor/TestOutlookTextExtractor.java index 3d276ce64..adbb966a8 100644 --- a/src/scratchpad/testcases/org/apache/poi/hsmf/extractor/TestOutlookTextExtractor.java +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/extractor/TestOutlookTextExtractor.java @@ -60,6 +60,8 @@ public final class TestOutlookTextExtractor extends POITestCase { String dateText = f.format(cal.getTime()); assertContains(text, "Date: " + dateText + "\n"); assertContains(text, "The quick brown fox jumps over the lazy dog"); + + ext.close(); } public void testSimple() throws Exception { @@ -77,21 +79,28 @@ public final class TestOutlookTextExtractor extends POITestCase { assertContains(text, "Subject: test message\n"); assertContains(text, "Date: Fri, 6 Jul 2007 05:27:17 +0000\n"); assertContains(text, "This is a test message."); + + ext.close(); } public void testConstructors() throws Exception { - String inp = (new OutlookTextExtactor(new FileInputStream( - samples.getFile("simple_test_msg.msg") - )).getText()); - String poifs = (new OutlookTextExtactor(new POIFSFileSystem(new FileInputStream( - samples.getFile("simple_test_msg.msg") - ))).getText()); - String mapi = (new OutlookTextExtactor(new MAPIMessage(new FileInputStream( - samples.getFile("simple_test_msg.msg") - ))).getText()); - - assertEquals(inp, poifs); - assertEquals(inp, mapi); + OutlookTextExtactor ext = new OutlookTextExtactor(new FileInputStream( + samples.getFile("simple_test_msg.msg"))); + String inp = ext.getText(); + ext.close(); + + ext = new OutlookTextExtactor(new POIFSFileSystem(new FileInputStream( + samples.getFile("simple_test_msg.msg")))); + String poifs = ext.getText(); + ext.close(); + + ext = new OutlookTextExtactor(new MAPIMessage(new FileInputStream( + samples.getFile("simple_test_msg.msg")))); + String mapi = ext.getText(); + ext.close(); + + assertEquals(inp, poifs); + assertEquals(inp, mapi); } /** @@ -128,6 +137,8 @@ public final class TestOutlookTextExtractor extends POITestCase { assertContains(text, "Subject: This is a test message please ignore\n"); assertContains(text, "Date:"); assertContains(text, "The quick brown fox jumps over the lazy dog"); + + ext.close(); } } @@ -164,6 +175,8 @@ public final class TestOutlookTextExtractor extends POITestCase { assertContains(text, "Subject: This is a test message please ignore\n"); assertContains(text, "Date: Mon, 11 Jan 2010 16:2"); // Exact times differ slightly assertContains(text, "The quick brown fox jumps over the lazy dog"); + + ext.close(); } } @@ -192,6 +205,8 @@ public final class TestOutlookTextExtractor extends POITestCase { // Embeded bits are checked in // TestExtractorFactory + + ext.close(); } public void testEncodings() throws Exception { @@ -209,5 +224,7 @@ public final class TestOutlookTextExtractor extends POITestCase { // And check some chinese bits assertContains(text, "(\u5f35\u6bd3\u502b)"); assertContains(text, "( MSG \u683c\u5f0f\u6e2c\u8a66 )"); + + ext.close(); } } diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/extractor/TestWordExtractor.java b/src/scratchpad/testcases/org/apache/poi/hwpf/extractor/TestWordExtractor.java index 82d6f34f4..1a69630a2 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/extractor/TestWordExtractor.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/extractor/TestWordExtractor.java @@ -20,6 +20,7 @@ package org.apache.poi.hwpf.extractor; import junit.framework.TestCase; import org.apache.poi.POIDataSamples; +import org.apache.poi.POITextExtractor; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFTestDataSamples; import org.apache.poi.hwpf.OldWordFileFormatException; @@ -377,10 +378,35 @@ public final class TestWordExtractor extends TestCase { for (Entry entry : fs.getRoot()) { if ("WordDocument".equals(entry.getName())) { WordExtractor ex = new WordExtractor(fs); - text = ex.getText(); + try { + text = ex.getText(); + } finally { + ex.close(); + } } } assertNotNull(text); } + + + public void testExtractorFromWord6Extractor() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(POIDataSamples.getHPSFInstance().openResourceAsStream("TestMickey.doc")); + Word6Extractor wExt = new Word6Extractor(fs); + try { + POITextExtractor ext = wExt.getMetadataTextExtractor(); + try { + // Now overall + String text = ext.getText(); + assertTrue(text.indexOf("TEMPLATE = Normal") > -1); + assertTrue(text.indexOf("SUBJECT = sample subject") > -1); + assertTrue(text.indexOf("MANAGER = sample manager") > -1); + assertTrue(text.indexOf("COMPANY = sample company") > -1); + } finally { + ext.close(); + } + } finally { + wExt.close(); + } + } } diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestCHPBinTable.java b/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestCHPBinTable.java index a36a729d5..d98390dac 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestCHPBinTable.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestCHPBinTable.java @@ -18,7 +18,7 @@ package org.apache.poi.hwpf.model; import java.io.ByteArrayOutputStream; -import java.util.ArrayList; +import java.util.List; import junit.framework.TestCase; @@ -59,16 +59,16 @@ public final class TestCHPBinTable CHPBinTable newBinTable = new CHPBinTable(newMainStream, newTableStream, 0, newTableStream.length, fakeTPT); - ArrayList oldTextRuns = _cHPBinTable._textRuns; - ArrayList newTextRuns = newBinTable._textRuns; + List oldTextRuns = _cHPBinTable._textRuns; + List newTextRuns = newBinTable._textRuns; assertEquals(oldTextRuns.size(), newTextRuns.size()); int size = oldTextRuns.size(); for (int x = 0; x < size; x++) { - PropertyNode oldNode = (PropertyNode)oldTextRuns.get(x); - PropertyNode newNode = (PropertyNode)newTextRuns.get(x); + CHPX oldNode = oldTextRuns.get(x); + CHPX newNode = newTextRuns.get(x); assertTrue(oldNode.equals(newNode)); } diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSectionTable.java b/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSectionTable.java index 61e537674..6fb92165c 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSectionTable.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/model/TestSectionTable.java @@ -20,7 +20,7 @@ package org.apache.poi.hwpf.model; import junit.framework.*; import java.io.ByteArrayOutputStream; -import java.util.ArrayList; +import java.util.List; import org.apache.poi.hwpf.*; import org.apache.poi.hwpf.model.io.*; @@ -58,8 +58,8 @@ public final class TestSectionTable newMainStream, newTableStream, 0, newTableStream.length, 0, tpt, fib.getSubdocumentTextStreamLength( SubdocumentType.MAIN )); - ArrayList oldSections = sectionTable.getSections(); - ArrayList newSections = newSectionTable.getSections(); + List oldSections = sectionTable.getSections(); + List newSections = newSectionTable.getSections(); assertEquals(oldSections.size(), newSections.size()); @@ -79,8 +79,8 @@ public final class TestSectionTable int size = oldSections.size(); for (int x = 0; x < size; x++) { - PropertyNode oldNode = (PropertyNode)oldSections.get(x); - PropertyNode newNode = (PropertyNode)newSections.get(x); + SEPX oldNode = oldSections.get(x); + SEPX newNode = newSections.get(x); assertEquals(oldNode, newNode); } } diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestLists.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestLists.java index eafb18fb9..d2c9ac95c 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestLists.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestLists.java @@ -23,6 +23,7 @@ import junit.framework.TestCase; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFTestDataSamples; +import org.apache.poi.hwpf.model.ListLevel; /** * Tests for our handling of lists @@ -207,4 +208,47 @@ public final class TestLists extends TestCase { assertEquals(1, r.getParagraph(22).getIlvl()); assertEquals(0, r.getParagraph(23).getIlvl()); } + + public void testSpecificNumberedOrderedListFeatures() throws IOException { + HWPFDocument doc = HWPFTestDataSamples.openSampleFile("Lists.doc"); + + Range r = doc.getRange(); + //these are in the numbered ordered list + //26 = OL 2 + //27 = OL 2.1 + //28 = OL 2.2 + //29 = OL 2.2.1 + for (int i = 26; i < 30; i++) { + Paragraph p = r.getParagraph(i); + assertTrue(p.isInList()); + HWPFList list = p.getList(); + ListLevel level = list.getLVL((char) p.getIlvl()); + assertFalse(level.isLegalNumbering()); + assertEquals(-1, level.getRestart()); + } + Paragraph p = r.getParagraph(26); + HWPFList list = p.getList(); + ListLevel level = list.getLVL((char) p.getIlvl()); + byte[] lvl = level.getLevelNumberingPlaceholderOffsets(); + + assertEquals((byte)1, lvl[0]); + assertEquals((byte)0, lvl[1]); + + p = r.getParagraph(27); + list = p.getList(); + level = list.getLVL((char) p.getIlvl()); + lvl = level.getLevelNumberingPlaceholderOffsets(); + assertEquals((byte)1, lvl[0]); + assertEquals((byte)3, lvl[1]); + + p = r.getParagraph(29); + list = p.getList(); + level = list.getLVL((char) p.getIlvl()); + lvl = level.getLevelNumberingPlaceholderOffsets(); + + assertEquals((byte)1, lvl[0]); + assertEquals((byte)3, lvl[1]); + assertEquals((byte)5, lvl[2]); + } + } diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRange.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRange.java index ab4a19673..a7eabe56a 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRange.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestRange.java @@ -17,7 +17,7 @@ package org.apache.poi.hwpf.usermodel; -import java.util.ArrayList; +import java.util.List; import junit.framework.TestCase; @@ -62,7 +62,7 @@ public final class TestRange extends TestCase HWPFDocument hwpfDocument = new HWPFDocument( POIDataSamples .getDocumentInstance().openResourceAsStream( "Bug46817.doc" ) ); - final ArrayList sections = hwpfDocument.getSectionTable() + final List sections = hwpfDocument.getSectionTable() .getSections(); assertEquals( sections.size(), 1 ); diff --git a/src/testcases/org/apache/poi/POITestCase.java b/src/testcases/org/apache/poi/POITestCase.java index 7a1a0274c..e38e46d4f 100644 --- a/src/testcases/org/apache/poi/POITestCase.java +++ b/src/testcases/org/apache/poi/POITestCase.java @@ -34,6 +34,21 @@ public class POITestCase extends TestCase { ); } + public static void assertEquals(T[] expected, T[] actual) + { + assertEquals("Non-matching lengths", expected.length, actual.length); + for (int i=0; i void assertContains(T needle, T[] haystack) { // Check diff --git a/src/testcases/org/apache/poi/TestPOIDocumentMain.java b/src/testcases/org/apache/poi/TestPOIDocumentMain.java index 67552588f..cacca43b3 100644 --- a/src/testcases/org/apache/poi/TestPOIDocumentMain.java +++ b/src/testcases/org/apache/poi/TestPOIDocumentMain.java @@ -26,7 +26,8 @@ import junit.framework.TestCase; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; /** * Tests that POIDocument correctly loads and saves the common @@ -72,7 +73,7 @@ public final class TestPOIDocumentMain extends TestCase { public void testWriteProperties() throws Exception { // Just check we can write them back out into a filesystem - POIFSFileSystem outFS = new POIFSFileSystem(); + NPOIFSFileSystem outFS = new NPOIFSFileSystem(); doc.readProperties(); doc.writeProperties(outFS); @@ -89,14 +90,14 @@ public final class TestPOIDocumentMain extends TestCase { ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Write them out - POIFSFileSystem outFS = new POIFSFileSystem(); + NPOIFSFileSystem outFS = new NPOIFSFileSystem(); doc.readProperties(); doc.writeProperties(outFS); outFS.writeFilesystem(baos); // Create a new version ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - POIFSFileSystem inFS = new POIFSFileSystem(bais); + OPOIFSFileSystem inFS = new OPOIFSFileSystem(bais); // Check they're still there doc.directory = inFS.getRoot(); diff --git a/src/testcases/org/apache/poi/ddf/TestEscherDump.java b/src/testcases/org/apache/poi/ddf/TestEscherDump.java index 5d05bb2f0..276c15f41 100644 --- a/src/testcases/org/apache/poi/ddf/TestEscherDump.java +++ b/src/testcases/org/apache/poi/ddf/TestEscherDump.java @@ -17,8 +17,13 @@ package org.apache.poi.ddf; +import static org.junit.Assert.*; + import java.io.ByteArrayInputStream; +import org.apache.poi.POIDataSamples; +import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.util.IOUtils; import org.junit.Test; public class TestEscherDump { @@ -36,4 +41,18 @@ public class TestEscherDump { public void testWithData() throws Exception { new EscherDump().dumpOld(8, new ByteArrayInputStream(new byte[] { 00, 00, 00, 00, 00, 00, 00, 00 }), System.out); } + + @Test + public void testWithSamplefile() throws Exception { + //InputStream stream = HSSFTestDataSamples.openSampleFileStream(") + byte[] data = POIDataSamples.getDDFInstance().readFile("Container.dat"); + new EscherDump().dump(data.length, data, System.out); + //new EscherDump().dumpOld(data.length, new ByteArrayInputStream(data), System.out); + + data = new byte[2586114]; + int bytes = IOUtils.readFully(HSSFTestDataSamples.openSampleFileStream("44593.xls"), data); + assertTrue(bytes != -1); + //new EscherDump().dump(bytes, data, System.out); + //new EscherDump().dumpOld(bytes, new ByteArrayInputStream(data), System.out); + } } diff --git a/src/testcases/org/apache/poi/hpsf/basic/TestHPSFBugs.java b/src/testcases/org/apache/poi/hpsf/basic/TestHPSFBugs.java index ff9ba878a..cd58e159f 100644 --- a/src/testcases/org/apache/poi/hpsf/basic/TestHPSFBugs.java +++ b/src/testcases/org/apache/poi/hpsf/basic/TestHPSFBugs.java @@ -31,7 +31,7 @@ import org.apache.poi.hpsf.PropertySetFactory; import org.apache.poi.hpsf.SummaryInformation; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; /** * Tests various bugs have been fixed @@ -109,8 +109,8 @@ public final class TestHPSFBugs extends TestCase { */ public void test54233() throws Exception { DocumentInputStream dis; - POIFSFileSystem fs = - new POIFSFileSystem(_samples.openResourceAsStream("TestNon4ByteBoundary.doc")); + NPOIFSFileSystem fs = + new NPOIFSFileSystem(_samples.openResourceAsStream("TestNon4ByteBoundary.doc")); dis = fs.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME); SummaryInformation si = (SummaryInformation)PropertySetFactory.create(dis); @@ -130,7 +130,7 @@ public final class TestHPSFBugs extends TestCase { ByteArrayOutputStream baos = new ByteArrayOutputStream(); doc.write(baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - doc = new HPSFPropertiesOnlyDocument(new POIFSFileSystem(bais)); + doc = new HPSFPropertiesOnlyDocument(new NPOIFSFileSystem(bais)); // Check properties are still there assertEquals("Microsoft Word 10.0", si.getApplicationName()); @@ -144,8 +144,8 @@ public final class TestHPSFBugs extends TestCase { */ public void test56138() throws Exception { DocumentInputStream dis; - POIFSFileSystem fs = - new POIFSFileSystem(_samples.openResourceAsStream("TestZeroLengthCodePage.mpp")); + NPOIFSFileSystem fs = + new NPOIFSFileSystem(_samples.openResourceAsStream("TestZeroLengthCodePage.mpp")); dis = fs.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME); SummaryInformation si = (SummaryInformation)PropertySetFactory.create(dis); diff --git a/src/testcases/org/apache/poi/hpsf/extractor/TestHPSFPropertiesExtractor.java b/src/testcases/org/apache/poi/hpsf/extractor/TestHPSFPropertiesExtractor.java index 22238d75f..0ef39719d 100644 --- a/src/testcases/org/apache/poi/hpsf/extractor/TestHPSFPropertiesExtractor.java +++ b/src/testcases/org/apache/poi/hpsf/extractor/TestHPSFPropertiesExtractor.java @@ -34,45 +34,53 @@ public final class TestHPSFPropertiesExtractor extends TestCase { public void testNormalProperties() throws Exception { POIFSFileSystem fs = new POIFSFileSystem(_samples.openResourceAsStream("TestMickey.doc")); HPSFPropertiesExtractor ext = new HPSFPropertiesExtractor(fs); - ext.getText(); - - // Check each bit in turn - String sinfText = ext.getSummaryInformationText(); - String dinfText = ext.getDocumentSummaryInformationText(); - - assertTrue(sinfText.indexOf("TEMPLATE = Normal") > -1); - assertTrue(sinfText.indexOf("SUBJECT = sample subject") > -1); - assertTrue(dinfText.indexOf("MANAGER = sample manager") > -1); - assertTrue(dinfText.indexOf("COMPANY = sample company") > -1); - - // Now overall - String text = ext.getText(); - assertTrue(text.indexOf("TEMPLATE = Normal") > -1); - assertTrue(text.indexOf("SUBJECT = sample subject") > -1); - assertTrue(text.indexOf("MANAGER = sample manager") > -1); - assertTrue(text.indexOf("COMPANY = sample company") > -1); + try { + ext.getText(); + + // Check each bit in turn + String sinfText = ext.getSummaryInformationText(); + String dinfText = ext.getDocumentSummaryInformationText(); + + assertTrue(sinfText.indexOf("TEMPLATE = Normal") > -1); + assertTrue(sinfText.indexOf("SUBJECT = sample subject") > -1); + assertTrue(dinfText.indexOf("MANAGER = sample manager") > -1); + assertTrue(dinfText.indexOf("COMPANY = sample company") > -1); + + // Now overall + String text = ext.getText(); + assertTrue(text.indexOf("TEMPLATE = Normal") > -1); + assertTrue(text.indexOf("SUBJECT = sample subject") > -1); + assertTrue(text.indexOf("MANAGER = sample manager") > -1); + assertTrue(text.indexOf("COMPANY = sample company") > -1); + } finally { + ext.close(); + } } public void testNormalUnicodeProperties() throws Exception { POIFSFileSystem fs = new POIFSFileSystem(_samples.openResourceAsStream("TestUnicode.xls")); HPSFPropertiesExtractor ext = new HPSFPropertiesExtractor(fs); - ext.getText(); - - // Check each bit in turn - String sinfText = ext.getSummaryInformationText(); - String dinfText = ext.getDocumentSummaryInformationText(); - - assertTrue(sinfText.indexOf("AUTHOR = marshall") > -1); - assertTrue(sinfText.indexOf("TITLE = Titel: \u00c4h") > -1); - assertTrue(dinfText.indexOf("COMPANY = Schreiner") > -1); - assertTrue(dinfText.indexOf("SCALE = false") > -1); - - // Now overall - String text = ext.getText(); - assertTrue(text.indexOf("AUTHOR = marshall") > -1); - assertTrue(text.indexOf("TITLE = Titel: \u00c4h") > -1); - assertTrue(text.indexOf("COMPANY = Schreiner") > -1); - assertTrue(text.indexOf("SCALE = false") > -1); + try { + ext.getText(); + + // Check each bit in turn + String sinfText = ext.getSummaryInformationText(); + String dinfText = ext.getDocumentSummaryInformationText(); + + assertTrue(sinfText.indexOf("AUTHOR = marshall") > -1); + assertTrue(sinfText.indexOf("TITLE = Titel: \u00c4h") > -1); + assertTrue(dinfText.indexOf("COMPANY = Schreiner") > -1); + assertTrue(dinfText.indexOf("SCALE = false") > -1); + + // Now overall + String text = ext.getText(); + assertTrue(text.indexOf("AUTHOR = marshall") > -1); + assertTrue(text.indexOf("TITLE = Titel: \u00c4h") > -1); + assertTrue(text.indexOf("COMPANY = Schreiner") > -1); + assertTrue(text.indexOf("SCALE = false") > -1); + } finally { + ext.close(); + } } public void testCustomProperties() throws Exception { @@ -80,18 +88,21 @@ public final class TestHPSFPropertiesExtractor extends TestCase { _samples.openResourceAsStream("TestMickey.doc") ); HPSFPropertiesExtractor ext = new HPSFPropertiesExtractor(fs); - - // Custom properties are part of the document info stream - String dinfText = ext.getDocumentSummaryInformationText(); - assertTrue(dinfText.indexOf("Client = sample client") > -1); - assertTrue(dinfText.indexOf("Division = sample division") > -1); - - String text = ext.getText(); - assertTrue(text.indexOf("Client = sample client") > -1); - assertTrue(text.indexOf("Division = sample division") > -1); + try { + // Custom properties are part of the document info stream + String dinfText = ext.getDocumentSummaryInformationText(); + assertTrue(dinfText.indexOf("Client = sample client") > -1); + assertTrue(dinfText.indexOf("Division = sample division") > -1); + + String text = ext.getText(); + assertTrue(text.indexOf("Client = sample client") > -1); + assertTrue(text.indexOf("Division = sample division") > -1); + } finally { + ext.close(); + } } - public void testConstructors() { + public void testConstructors() throws IOException { POIFSFileSystem fs; HSSFWorkbook wb; try { @@ -102,9 +113,29 @@ public final class TestHPSFPropertiesExtractor extends TestCase { } ExcelExtractor excelExt = new ExcelExtractor(wb); - String fsText = (new HPSFPropertiesExtractor(fs)).getText(); - String hwText = (new HPSFPropertiesExtractor(wb)).getText(); - String eeText = (new HPSFPropertiesExtractor(excelExt)).getText(); + final String fsText; + HPSFPropertiesExtractor fsExt = new HPSFPropertiesExtractor(fs); + try { + fsText = fsExt.getText(); + } finally { + fsExt.close(); + } + + final String hwText; + HPSFPropertiesExtractor hwExt = new HPSFPropertiesExtractor(wb); + try { + hwText = hwExt.getText(); + } finally { + hwExt.close(); + } + + final String eeText; + HPSFPropertiesExtractor eeExt = new HPSFPropertiesExtractor(excelExt); + try { + eeText = eeExt.getText(); + } finally { + eeExt.close(); + } assertEquals(fsText, hwText); assertEquals(fsText, eeText); @@ -113,13 +144,17 @@ public final class TestHPSFPropertiesExtractor extends TestCase { assertTrue(fsText.indexOf("TITLE = Titel: \u00c4h") > -1); } - public void test42726() { - HPSFPropertiesExtractor ex = new HPSFPropertiesExtractor(HSSFTestDataSamples.openSampleWorkbook("42726.xls")); - String txt = ex.getText(); - assertTrue(txt.indexOf("PID_AUTHOR") != -1); - assertTrue(txt.indexOf("PID_EDITTIME") != -1); - assertTrue(txt.indexOf("PID_REVNUMBER") != -1); - assertTrue(txt.indexOf("PID_THUMBNAIL") != -1); + public void test42726() throws IOException { + HPSFPropertiesExtractor ext = new HPSFPropertiesExtractor(HSSFTestDataSamples.openSampleWorkbook("42726.xls")); + try { + String txt = ext.getText(); + assertTrue(txt.indexOf("PID_AUTHOR") != -1); + assertTrue(txt.indexOf("PID_EDITTIME") != -1); + assertTrue(txt.indexOf("PID_REVNUMBER") != -1); + assertTrue(txt.indexOf("PID_THUMBNAIL") != -1); + } finally { + ext.close(); + } } public void testThumbnail() throws Exception { diff --git a/src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java b/src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java index 51cc0ed45..d544b0b79 100644 --- a/src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java +++ b/src/testcases/org/apache/poi/hssf/HSSFITestDataProvider.java @@ -17,6 +17,8 @@ package org.apache.poi.hssf; +import java.io.InputStream; + import org.apache.poi.POIDataSamples; import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator; import org.apache.poi.hssf.usermodel.HSSFWorkbook; @@ -38,6 +40,9 @@ public final class HSSFITestDataProvider implements ITestDataProvider { public HSSFWorkbook openSampleWorkbook(String sampleFileName) { return HSSFTestDataSamples.openSampleWorkbook(sampleFileName); } + public InputStream openWorkbookStream(String sampleFileName) { + return HSSFTestDataSamples.openSampleFileStream(sampleFileName); + } public HSSFWorkbook writeOutAndReadBack(Workbook original) { if(!(original instanceof HSSFWorkbook)) { diff --git a/src/testcases/org/apache/poi/hssf/dev/BaseXLSIteratingTest.java b/src/testcases/org/apache/poi/hssf/dev/BaseXLSIteratingTest.java index 521b9ad67..0adb2cf98 100644 --- a/src/testcases/org/apache/poi/hssf/dev/BaseXLSIteratingTest.java +++ b/src/testcases/org/apache/poi/hssf/dev/BaseXLSIteratingTest.java @@ -79,11 +79,11 @@ public abstract class BaseXLSIteratingTest { try { runOneFile(dir, file, failed); } catch (Exception e) { - System.out.println("Failed: " + file); if(SILENT_EXCLUDED.contains(file)) { continue; } + System.out.println("Failed: " + file); e.printStackTrace(); // try to read it in HSSFWorkbook to quickly fail if we cannot read the file there at all and thus probably can use SILENT_EXCLUDED instead diff --git a/src/testcases/org/apache/poi/hssf/eventusermodel/TestHSSFEventFactory.java b/src/testcases/org/apache/poi/hssf/eventusermodel/TestHSSFEventFactory.java index 976633108..0a111beaa 100644 --- a/src/testcases/org/apache/poi/hssf/eventusermodel/TestHSSFEventFactory.java +++ b/src/testcases/org/apache/poi/hssf/eventusermodel/TestHSSFEventFactory.java @@ -22,107 +22,182 @@ import java.util.List; import junit.framework.TestCase; +import org.apache.poi.EncryptedDocumentException; import org.apache.poi.hssf.HSSFTestDataSamples; +import org.apache.poi.hssf.record.BoundSheetRecord; import org.apache.poi.hssf.record.ContinueRecord; import org.apache.poi.hssf.record.DVALRecord; import org.apache.poi.hssf.record.DVRecord; import org.apache.poi.hssf.record.EOFRecord; import org.apache.poi.hssf.record.FeatHdrRecord; +import org.apache.poi.hssf.record.NumberRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.SelectionRecord; import org.apache.poi.hssf.record.WindowTwoRecord; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.poifs.filesystem.POIFSFileSystem; + /** - * + * Testing for {@link HSSFEventFactory} */ public final class TestHSSFEventFactory extends TestCase { - - private static final InputStream openSample(String sampleFileName) { - return HSSFTestDataSamples.openSampleFileStream(sampleFileName); - } + private static final InputStream openSample(String sampleFileName) { + return HSSFTestDataSamples.openSampleFileStream(sampleFileName); + } - public void testWithMissingRecords() throws Exception { + public void testWithMissingRecords() throws Exception { - HSSFRequest req = new HSSFRequest(); - MockHSSFListener mockListen = new MockHSSFListener(); - req.addListenerForAllRecords(mockListen); - - POIFSFileSystem fs = new POIFSFileSystem(openSample("SimpleWithSkip.xls")); - HSSFEventFactory factory = new HSSFEventFactory(); - factory.processWorkbookEvents(req, fs); + HSSFRequest req = new HSSFRequest(); + MockHSSFListener mockListen = new MockHSSFListener(); + req.addListenerForAllRecords(mockListen); - Record[] recs = mockListen.getRecords(); - // Check we got the records - assertTrue( recs.length > 100 ); - - // Check that the last few records are as we expect - // (Makes sure we don't accidently skip the end ones) - int numRec = recs.length; - assertEquals(WindowTwoRecord.class, recs[numRec-3].getClass()); - assertEquals(SelectionRecord.class, recs[numRec-2].getClass()); - assertEquals(EOFRecord.class, recs[numRec-1].getClass()); - } + POIFSFileSystem fs = new POIFSFileSystem(openSample("SimpleWithSkip.xls")); + HSSFEventFactory factory = new HSSFEventFactory(); + factory.processWorkbookEvents(req, fs); - public void testWithCrazyContinueRecords() throws Exception { - // Some files have crazy ordering of their continue records - // Check that we don't break on them (bug #42844) - - HSSFRequest req = new HSSFRequest(); - MockHSSFListener mockListen = new MockHSSFListener(); - req.addListenerForAllRecords(mockListen); - - POIFSFileSystem fs = new POIFSFileSystem(openSample("ContinueRecordProblem.xls")); - HSSFEventFactory factory = new HSSFEventFactory(); - factory.processWorkbookEvents(req, fs); + Record[] recs = mockListen.getRecords(); + // Check we got the records + assertTrue( recs.length > 100 ); - Record[] recs = mockListen.getRecords(); - // Check we got the records - assertTrue( recs.length > 100 ); + // Check that the last few records are as we expect + // (Makes sure we don't accidently skip the end ones) + int numRec = recs.length; + assertEquals(WindowTwoRecord.class, recs[numRec-3].getClass()); + assertEquals(SelectionRecord.class, recs[numRec-2].getClass()); + assertEquals(EOFRecord.class, recs[numRec-1].getClass()); + } - // And none of them are continue ones - for(int i=0; i 100 ); - assertTrue("no errors while processing the file", true); - } + // And none of them are continue ones + for(int i=0; i records = new ArrayList(); + // Check that the last few records are as we expect + // (Makes sure we don't accidently skip the end ones) + int numRec = recs.length; + assertEquals(DVALRecord.class, recs[numRec-4].getClass()); + assertEquals(DVRecord.class, recs[numRec-3].getClass()); + assertEquals(FeatHdrRecord.class, recs[numRec-2].getClass()); + assertEquals(EOFRecord.class, recs[numRec-1].getClass()); + } - public MockHSSFListener() {} - public Record[] getRecords() { - Record[] result = new Record[records.size()]; - records.toArray(result); - return result; - } + /** + * Unknown records can be continued. + * Check that HSSFEventFactory doesn't break on them. + * (the test file was provided in a reopen of bug #42844) + */ + public void testUnknownContinueRecords() throws Exception { - public void processRecord(Record record) { - records.add(record); - } - } + HSSFRequest req = new HSSFRequest(); + MockHSSFListener mockListen = new MockHSSFListener(); + req.addListenerForAllRecords(mockListen); + + POIFSFileSystem fs = new POIFSFileSystem(openSample("42844.xls")); + HSSFEventFactory factory = new HSSFEventFactory(); + factory.processWorkbookEvents(req, fs); + } + + private static class MockHSSFListener implements HSSFListener { + private final List records = new ArrayList(); + + public MockHSSFListener() {} + public Record[] getRecords() { + Record[] result = new Record[records.size()]; + records.toArray(result); + return result; + } + + public void processRecord(Record record) { + records.add(record); + } + } + + public void testWithDifferentWorkbookName() throws Exception { + HSSFRequest req = new HSSFRequest(); + MockHSSFListener mockListen = new MockHSSFListener(); + req.addListenerForAllRecords(mockListen); + + POIFSFileSystem fs = new POIFSFileSystem(openSample("BOOK_in_capitals.xls")); + HSSFEventFactory factory = new HSSFEventFactory(); + factory.processWorkbookEvents(req, fs); + + fs = new POIFSFileSystem(openSample("WORKBOOK_in_capitals.xls")); + factory = new HSSFEventFactory(); + factory.processWorkbookEvents(req, fs); + } + + public void testWithPasswordProtectedWorkbooks() throws Exception { + HSSFRequest req = new HSSFRequest(); + MockHSSFListener mockListen = new MockHSSFListener(); + req.addListenerForAllRecords(mockListen); + + // Without a password, can't be read + Biff8EncryptionKey.setCurrentUserPassword(null); + POIFSFileSystem fs = new POIFSFileSystem(openSample("xor-encryption-abc.xls")); + + HSSFEventFactory factory = new HSSFEventFactory(); + try { + factory.processWorkbookEvents(req, fs); + fail("Shouldn't be able to process protected workbook without the password"); + } catch (EncryptedDocumentException e) {} + + + // With the password, is properly processed + Biff8EncryptionKey.setCurrentUserPassword("abc"); + + req = new HSSFRequest(); + mockListen = new MockHSSFListener(); + req.addListenerForAllRecords(mockListen); + factory.processWorkbookEvents(req, fs); + + // Check we got the sheet and the contents + Record[] recs = mockListen.getRecords(); + assertTrue( recs.length > 50 ); + + // Has one sheet, with values 1,2,3 in column A rows 1-3 + boolean hasSheet=false, hasA1=false, hasA2=false, hasA3=false; + for (Record r : recs) { + if (r instanceof BoundSheetRecord) { + BoundSheetRecord bsr = (BoundSheetRecord)r; + assertEquals("Sheet1", bsr.getSheetname()); + hasSheet = true; + } + if (r instanceof NumberRecord) { + NumberRecord nr = (NumberRecord)r; + if (nr.getColumn() == 0 && nr.getRow() == 0) { + assertEquals(1, (int)nr.getValue()); + hasA1 = true; + } + if (nr.getColumn() == 0 && nr.getRow() == 1) { + assertEquals(2, (int)nr.getValue()); + hasA2 = true; + } + if (nr.getColumn() == 0 && nr.getRow() == 2) { + assertEquals(3, (int)nr.getValue()); + hasA3 = true; + } + } + } + + assertTrue("Sheet record not found", hasSheet); + assertTrue("Numeric record for A1 not found", hasA1); + assertTrue("Numeric record for A2 not found", hasA2); + assertTrue("Numeric record for A3 not found", hasA3); + } } diff --git a/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java b/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java index de8221029..793215a02 100644 --- a/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java +++ b/src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java @@ -46,15 +46,18 @@ public final class TestExcelExtractor extends TestCase { } - public void testSimple() { - + public void testSimple() throws IOException { ExcelExtractor extractor = createExtractor("Simple.xls"); - assertEquals("Sheet1\nreplaceMe\nSheet2\nSheet3\n", extractor.getText()); - - // Now turn off sheet names - extractor.setIncludeSheetNames(false); - assertEquals("replaceMe\n", extractor.getText()); + try { + assertEquals("Sheet1\nreplaceMe\nSheet2\nSheet3\n", extractor.getText()); + + // Now turn off sheet names + extractor.setIncludeSheetNames(false); + assertEquals("replaceMe\n", extractor.getText()); + } finally { + extractor.close(); + } } public void testNumericFormula() { @@ -126,45 +129,47 @@ public final class TestExcelExtractor extends TestCase { public void testEventExtractor() throws Exception { - EventBasedExcelExtractor extractor; - // First up, a simple file with string // based formulas in it - extractor = new EventBasedExcelExtractor( + EventBasedExcelExtractor extractor = new EventBasedExcelExtractor( new POIFSFileSystem( HSSFTestDataSamples.openSampleFileStream("SimpleWithFormula.xls") ) ); - extractor.setIncludeSheetNames(true); - - String text = extractor.getText(); - assertEquals("Sheet1\nreplaceme\nreplaceme\nreplacemereplaceme\nSheet2\nSheet3\n", text); - - extractor.setIncludeSheetNames(false); - extractor.setFormulasNotResults(true); - - text = extractor.getText(); - assertEquals("replaceme\nreplaceme\nCONCATENATE(A1,A2)\n", text); - - - // Now, a slightly longer file with numeric formulas - extractor = new EventBasedExcelExtractor( - new POIFSFileSystem( - HSSFTestDataSamples.openSampleFileStream("sumifformula.xls") - ) - ); - extractor.setIncludeSheetNames(false); - extractor.setFormulasNotResults(true); - - text = extractor.getText(); - assertEquals( - "1000\t1\tSUMIF(A1:A5,\">4000\",B1:B5)\n" + - "2000\t2\n" + - "3000\t3\n" + - "4000\t4\n" + - "5000\t5\n", - text - ); + try { + extractor.setIncludeSheetNames(true); + + String text = extractor.getText(); + assertEquals("Sheet1\nreplaceme\nreplaceme\nreplacemereplaceme\nSheet2\nSheet3\n", text); + + extractor.setIncludeSheetNames(false); + extractor.setFormulasNotResults(true); + + text = extractor.getText(); + assertEquals("replaceme\nreplaceme\nCONCATENATE(A1,A2)\n", text); + + + // Now, a slightly longer file with numeric formulas + extractor = new EventBasedExcelExtractor( + new POIFSFileSystem( + HSSFTestDataSamples.openSampleFileStream("sumifformula.xls") + ) + ); + extractor.setIncludeSheetNames(false); + extractor.setFormulasNotResults(true); + + text = extractor.getText(); + assertEquals( + "1000\t1\tSUMIF(A1:A5,\">4000\",B1:B5)\n" + + "2000\t2\n" + + "3000\t3\n" + + "4000\t4\n" + + "5000\t5\n", + text + ); + } finally { + extractor.close(); + } } public void testWithComments() { @@ -272,15 +277,22 @@ public final class TestExcelExtractor extends TestCase { HSSFWorkbook wbB = new HSSFWorkbook(dirB, fs, true); ExcelExtractor exA = new ExcelExtractor(wbA); - ExcelExtractor exB = new ExcelExtractor(wbB); - - assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", - exA.getText()); - assertEquals("Sample Excel", exA.getSummaryInformation().getTitle()); - - assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", - exB.getText()); - assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle()); + try { + ExcelExtractor exB = new ExcelExtractor(wbB); + try { + assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", + exA.getText()); + assertEquals("Sample Excel", exA.getSummaryInformation().getTitle()); + + assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", + exB.getText()); + assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle()); + } finally { + exB.close(); + } + } finally { + exA.close(); + } } /** @@ -299,21 +311,32 @@ public final class TestExcelExtractor extends TestCase { HSSFWorkbook wbB = new HSSFWorkbook(dirB, fs, true); ExcelExtractor exA = new ExcelExtractor(wbA); - ExcelExtractor exB = new ExcelExtractor(wbB); - - assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", - exA.getText()); - assertEquals("Sample Excel", exA.getSummaryInformation().getTitle()); - - assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", - exB.getText()); - assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle()); - - // And the base file too - ExcelExtractor ex = new ExcelExtractor(fs); - assertEquals("Sheet1\nI have lots of embeded files in me\nSheet2\nSheet3\n", - ex.getText()); - assertEquals("Excel With Embeded", ex.getSummaryInformation().getTitle()); + try { + ExcelExtractor exB = new ExcelExtractor(wbB); + try { + assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", + exA.getText()); + assertEquals("Sample Excel", exA.getSummaryInformation().getTitle()); + + assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", + exB.getText()); + assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle()); + + // And the base file too + ExcelExtractor ex = new ExcelExtractor(fs); + try { + assertEquals("Sheet1\nI have lots of embeded files in me\nSheet2\nSheet3\n", + ex.getText()); + assertEquals("Excel With Embeded", ex.getSummaryInformation().getTitle()); + } finally { + ex.close(); + } + } finally { + exB.close(); + } + } finally { + exA.close(); + } } /** @@ -340,4 +363,10 @@ public final class TestExcelExtractor extends TestCase { assertTrue(text.contains("ZIP")); } + + public void testNullPointerException() { + ExcelExtractor extractor = createExtractor("ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls"); + assertNotNull(extractor); + assertNotNull(extractor.getText()); + } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java index ca8e255c1..c62c36522 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java +++ b/src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java @@ -51,8 +51,6 @@ import org.apache.poi.util.HexRead; * @author Evgeniy Berlog */ public class TestDrawingAggregate extends TestCase { - - /** * information about drawing aggregate in a worksheet */ @@ -189,7 +187,15 @@ public class TestDrawingAggregate extends TestCase { // System.out.println("[WARN] Cannot read " + file.getName()); continue; } - assertWriteAndReadBack(wb); + try { + assertWriteAndReadBack(wb); + } catch (Exception e) { + String filename = file.getName(); + System.out.println("Drawing Aggregate re-write test failed for " + filename); + e.printStackTrace(System.out); + + fail("Error when writing and re-reading workbook " + filename + "\n" + e); + } } } diff --git a/src/testcases/org/apache/poi/hssf/model/TestShapes.java b/src/testcases/org/apache/poi/hssf/model/TestShapes.java index d17178ee7..beed4a1d3 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestShapes.java +++ b/src/testcases/org/apache/poi/hssf/model/TestShapes.java @@ -20,6 +20,7 @@ package org.apache.poi.hssf.model; import junit.framework.TestCase; + import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFComment; @@ -37,7 +38,8 @@ public final class TestShapes extends TestCase { * * See Bug 51332 */ - public void testShapeId(){ + @SuppressWarnings("deprecation") + public void testShapeId(){ HSSFClientAnchor anchor = new HSSFClientAnchor(); AbstractShape shape; diff --git a/src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java b/src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java index 239f2092f..9c9b5486c 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestCFHeaderRecord.java @@ -23,16 +23,11 @@ import junit.framework.TestCase; import org.apache.poi.ss.util.CellRangeAddress; /** - * Tests the serialization and deserialization of the TestCFHeaderRecord - * class works correctly. - * - * @author Dmitriy Kumshayev + * Tests the serialization and deserialization of the {@link CFHeaderRecord} + * and {@link CFHeader12Record} classes works correctly. */ -public final class TestCFHeaderRecord extends TestCase -{ - - public void testCreateCFHeaderRecord () - { +public final class TestCFHeaderRecord extends TestCase { + public void testCreateCFHeaderRecord () { CFHeaderRecord record = new CFHeaderRecord(); CellRangeAddress[] ranges = { new CellRangeAddress(0,0xFFFF,5,5), @@ -50,12 +45,52 @@ public final class TestCFHeaderRecord extends TestCase assertEquals(65535, enclosingCellRange.getLastRow()); assertEquals(0, enclosingCellRange.getFirstColumn()); assertEquals(6, enclosingCellRange.getLastColumn()); + + assertEquals(false, record.getNeedRecalculation()); + assertEquals(0, record.getID()); + record.setNeedRecalculation(true); - assertTrue(record.getNeedRecalculation()); + assertEquals(true, record.getNeedRecalculation()); + assertEquals(0, record.getID()); + + record.setID(7); record.setNeedRecalculation(false); - assertFalse(record.getNeedRecalculation()); + assertEquals(false, record.getNeedRecalculation()); + assertEquals(7, record.getID()); } + public void testCreateCFHeader12Record () { + CFHeader12Record record = new CFHeader12Record(); + CellRangeAddress[] ranges = { + new CellRangeAddress(0,0xFFFF,5,5), + new CellRangeAddress(0,0xFFFF,6,6), + new CellRangeAddress(0,1,0,1), + new CellRangeAddress(0,1,2,3), + new CellRangeAddress(2,3,0,1), + new CellRangeAddress(2,3,2,3), + }; + record.setCellRanges(ranges); + ranges = record.getCellRanges(); + assertEquals(6,ranges.length); + CellRangeAddress enclosingCellRange = record.getEnclosingCellRange(); + assertEquals(0, enclosingCellRange.getFirstRow()); + assertEquals(65535, enclosingCellRange.getLastRow()); + assertEquals(0, enclosingCellRange.getFirstColumn()); + assertEquals(6, enclosingCellRange.getLastColumn()); + + assertEquals(false, record.getNeedRecalculation()); + assertEquals(0, record.getID()); + + record.setNeedRecalculation(true); + assertEquals(true, record.getNeedRecalculation()); + assertEquals(0, record.getID()); + + record.setID(7); + record.setNeedRecalculation(false); + assertEquals(false, record.getNeedRecalculation()); + assertEquals(7, record.getID()); + } + public void testSerialization() { byte[] recordData = { diff --git a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java index c5da21875..c39e3e404 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestCFRuleRecord.java @@ -21,7 +21,8 @@ import static org.junit.Assert.assertArrayEquals; import junit.framework.AssertionFailedError; import junit.framework.TestCase; -import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator; +import org.apache.poi.hssf.HSSFITestDataProvider; +import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator; import org.apache.poi.hssf.record.cf.BorderFormatting; import org.apache.poi.hssf.record.cf.FontFormatting; import org.apache.poi.hssf.record.cf.PatternFormatting; @@ -31,14 +32,15 @@ import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.ptg.RefNPtg; import org.apache.poi.ss.formula.ptg.RefPtg; +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.util.LittleEndian; /** * Tests the serialization and deserialization of the TestCFRuleRecord * class works correctly. - * - * @author Dmitriy Kumshayev */ +@SuppressWarnings("resource") public final class TestCFRuleRecord extends TestCase { public void testConstructors () { HSSFWorkbook workbook = new HSSFWorkbook(); @@ -91,19 +93,77 @@ public final class TestCFRuleRecord extends TestCase { } } + public void testCreateCFRule12Record() { + HSSFWorkbook workbook = new HSSFWorkbook(); + HSSFSheet sheet = workbook.createSheet(); + CFRule12Record record = CFRule12Record.create(sheet, "7"); + testCFRule12Record(record); + + // Serialize + byte [] serializedRecord = record.serialize(); + + // Strip header + byte [] recordData = new byte[serializedRecord.length-4]; + System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length); + + // Deserialize + record = new CFRule12Record(TestcaseRecordInputStream.create(CFRule12Record.sid, recordData)); + + // Serialize again + byte[] output = record.serialize(); + + // Compare + assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength + + for (int i = 0; i < recordData.length;i++) + { + assertEquals("CFRule12Record doesn't match", recordData[i], output[i+4]); + } + } + + public void testCreateIconCFRule12Record() { + HSSFWorkbook workbook = new HSSFWorkbook(); + HSSFSheet sheet = workbook.createSheet(); + CFRule12Record record = CFRule12Record.create(sheet, IconSet.GREY_5_ARROWS); + record.getMultiStateFormatting().getThresholds()[1].setType(RangeType.PERCENT.id); + record.getMultiStateFormatting().getThresholds()[1].setValue(10d); + record.getMultiStateFormatting().getThresholds()[2].setType(RangeType.NUMBER.id); + record.getMultiStateFormatting().getThresholds()[2].setValue(-4d); + + // Check it + testCFRule12Record(record); + assertEquals(IconSet.GREY_5_ARROWS, record.getMultiStateFormatting().getIconSet()); + assertEquals(5, record.getMultiStateFormatting().getThresholds().length); + + // Serialize + byte [] serializedRecord = record.serialize(); + + // Strip header + byte [] recordData = new byte[serializedRecord.length-4]; + System.arraycopy(serializedRecord, 4, recordData, 0, recordData.length); + + // Deserialize + record = new CFRule12Record(TestcaseRecordInputStream.create(CFRule12Record.sid, recordData)); + + // Check it has the icon, and the right number of thresholds + assertEquals(IconSet.GREY_5_ARROWS, record.getMultiStateFormatting().getIconSet()); + assertEquals(5, record.getMultiStateFormatting().getThresholds().length); + + // Serialize again + byte[] output = record.serialize(); + + // Compare + assertEquals("Output size", recordData.length+4, output.length); //includes sid+recordlength + + for (int i = 0; i < recordData.length;i++) + { + assertEquals("CFRule12Record doesn't match", recordData[i], output[i+4]); + } + } + private void testCFRuleRecord(CFRuleRecord record) { - FontFormatting fontFormatting = new FontFormatting(); - testFontFormattingAccessors(fontFormatting); - assertFalse(record.containsFontFormattingBlock()); - record.setFontFormatting(fontFormatting); - assertTrue(record.containsFontFormattingBlock()); - - BorderFormatting borderFormatting = new BorderFormatting(); - testBorderFormattingAccessors(borderFormatting); - assertFalse(record.containsBorderFormattingBlock()); - record.setBorderFormatting(borderFormatting); - assertTrue(record.containsBorderFormattingBlock()); - + testCFRuleBase(record); + assertFalse(record.isLeftBorderModified()); record.setLeftBorderModified(true); assertTrue(record.isLeftBorderModified()); @@ -129,12 +189,6 @@ public final class TestCFRuleRecord extends TestCase { assertTrue(record.isBottomLeftTopRightBorderModified()); - PatternFormatting patternFormatting = new PatternFormatting(); - testPatternFormattingAccessors(patternFormatting); - assertFalse(record.containsPatternFormattingBlock()); - record.setPatternFormatting(patternFormatting); - assertTrue(record.containsPatternFormattingBlock()); - assertFalse(record.isPatternBackgroundColorModified()); record.setPatternBackgroundColorModified(true); assertTrue(record.isPatternBackgroundColorModified()); @@ -147,6 +201,30 @@ public final class TestCFRuleRecord extends TestCase { record.setPatternStyleModified(true); assertTrue(record.isPatternStyleModified()); } + private void testCFRule12Record(CFRule12Record record) { + assertEquals(CFRule12Record.sid, record.getFutureRecordType()); + assertEquals("A1", record.getAssociatedRange().formatAsString()); + testCFRuleBase(record); + } + private void testCFRuleBase(CFRuleBase record) { + FontFormatting fontFormatting = new FontFormatting(); + testFontFormattingAccessors(fontFormatting); + assertFalse(record.containsFontFormattingBlock()); + record.setFontFormatting(fontFormatting); + assertTrue(record.containsFontFormattingBlock()); + + BorderFormatting borderFormatting = new BorderFormatting(); + testBorderFormattingAccessors(borderFormatting); + assertFalse(record.containsBorderFormattingBlock()); + record.setBorderFormatting(borderFormatting); + assertTrue(record.containsBorderFormattingBlock()); + + PatternFormatting patternFormatting = new PatternFormatting(); + testPatternFormattingAccessors(patternFormatting); + assertFalse(record.containsPatternFormattingBlock()); + record.setPatternFormatting(patternFormatting); + assertTrue(record.containsPatternFormattingBlock()); + } private void testPatternFormattingAccessors(PatternFormatting patternFormatting) { patternFormatting.setFillBackgroundColor(HSSFColor.GREEN.index); @@ -365,4 +443,11 @@ public final class TestCFRuleRecord extends TestCase { byte [] serializedClone = clone.serialize(); assertArrayEquals(serializedRecord, serializedClone); } + + public void testBug57231_rewrite() { + HSSFWorkbook wb = HSSFITestDataProvider.instance.openSampleWorkbook("57231_MixedGasReport.xls"); + assertEquals(7, wb.getNumberOfSheets()); + wb = HSSFITestDataProvider.instance.writeOutAndReadBack(wb); + assertEquals(7, wb.getNumberOfSheets()); + } } diff --git a/src/testcases/org/apache/poi/hssf/record/TestNameRecord.java b/src/testcases/org/apache/poi/hssf/record/TestNameRecord.java index 28bfb3509..231b6c92c 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestNameRecord.java +++ b/src/testcases/org/apache/poi/hssf/record/TestNameRecord.java @@ -17,15 +17,19 @@ package org.apache.poi.hssf.record; +import java.io.IOException; + +import junit.framework.TestCase; + import org.apache.poi.hssf.usermodel.HSSFName; import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.formula.ptg.ArrayPtg; +import org.apache.poi.ss.formula.ptg.NamePtg; import org.apache.poi.ss.formula.ptg.Ptg; +import org.apache.poi.ss.formula.ptg.Ref3DPtg; import org.apache.poi.util.HexRead; -import junit.framework.AssertionFailedError; -import junit.framework.TestCase; - /** * Tests the NameRecord serializes/deserializes correctly * @@ -60,7 +64,8 @@ public final class TestNameRecord extends TestCase { byte[] data2 = nr.serialize(); TestcaseRecordInputStream.confirmRecordEncoding(NameRecord.sid, data, data2); } - public void testFormulaRelAbs_bug46174() { + + public void testFormulaRelAbs_bug46174() throws IOException { // perhaps this testcase belongs on TestHSSFName HSSFWorkbook wb = new HSSFWorkbook(); HSSFName name = wb.createName(); @@ -68,11 +73,13 @@ public final class TestNameRecord extends TestCase { name.setNameName("test"); name.setRefersToFormula("Sheet1!$B$3"); if (name.getRefersToFormula().equals("Sheet1!B3")) { - throw new AssertionFailedError("Identified bug 46174"); + fail("Identified bug 46174"); } assertEquals("Sheet1!$B$3", name.getRefersToFormula()); + wb.close(); } - public void testFormulaGeneral() { + + public void testFormulaGeneral() throws IOException { // perhaps this testcase belongs on TestHSSFName HSSFWorkbook wb = new HSSFWorkbook(); HSSFName name = wb.createName(); @@ -82,6 +89,8 @@ public final class TestNameRecord extends TestCase { assertEquals("Sheet1!A1+Sheet1!A2", name.getRefersToFormula()); name.setRefersToFormula("5*6"); assertEquals("5*6", name.getRefersToFormula()); + + wb.close(); } /** @@ -687,4 +696,22 @@ public final class TestNameRecord extends TestCase { assertEquals("1.T20.001", vals[0][0]); assertEquals("1.T20.010", vals[vals.length - 1][0]); } + + public void testBug57923() { + NameRecord record = new NameRecord(); + assertEquals(0, record.getExternSheetNumber()); + + record.setNameDefinition(new Ptg[] {}); + assertEquals(0, record.getExternSheetNumber()); + + record.setNameDefinition(new Ptg[] {new NamePtg(1)}); + assertEquals(0, record.getExternSheetNumber()); + + record.setNameDefinition(new Ptg[] {new Area3DPtg("area", 1)}); + assertEquals(1, record.getExternSheetNumber()); + + record.setNameDefinition(new Ptg[] {new Ref3DPtg("A1", 1)}); + assertEquals(1, record.getExternSheetNumber()); + } + } diff --git a/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java b/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java index 2b236e1ac..518c5f047 100644 --- a/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java +++ b/src/testcases/org/apache/poi/hssf/record/TestRecordInputStream.java @@ -94,4 +94,12 @@ public final class TestRecordInputStream extends TestCase { String actual = in.readString(); assertEquals("Multilingual - \u591A\u8A00\u8A9E", actual); } + + public void testLeftoverDataException() { + // just ensure that the exception is created correctly, even with unknown sids + new RecordInputStream.LeftoverDataException(1, 200); + new RecordInputStream.LeftoverDataException(0, 200); + new RecordInputStream.LeftoverDataException(999999999, 200); + new RecordInputStream.LeftoverDataException(HeaderRecord.sid, 200); + } } diff --git a/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java b/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java index 1e153bc45..c58f401bc 100644 --- a/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java +++ b/src/testcases/org/apache/poi/hssf/record/aggregates/TestCFRecordsAggregate.java @@ -26,107 +26,133 @@ import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.poi.hssf.model.RecordStream; +import org.apache.poi.hssf.record.CFHeaderBase; import org.apache.poi.hssf.record.CFHeaderRecord; +import org.apache.poi.hssf.record.CFRule12Record; +import org.apache.poi.hssf.record.CFRuleBase; +import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator; import org.apache.poi.hssf.record.CFRuleRecord; +import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.RecordFactory; -import org.apache.poi.hssf.record.CFRuleRecord.ComparisonOperator; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.LittleEndian; /** * Tests the serialization and deserialization of the CFRecordsAggregate * class works correctly. - * - * @author Dmitriy Kumshayev */ -public final class TestCFRecordsAggregate extends TestCase -{ - - public void testCFRecordsAggregate() - { - HSSFWorkbook workbook = new HSSFWorkbook(); +@SuppressWarnings("resource") +public final class TestCFRecordsAggregate extends TestCase { + public void testCFRecordsAggregate() { + HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(); - List recs = new ArrayList(); - CFHeaderRecord header = new CFHeaderRecord(); - CFRuleRecord rule1 = CFRuleRecord.create(sheet, "7"); - CFRuleRecord rule2 = CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "2", "5"); - CFRuleRecord rule3 = CFRuleRecord.create(sheet, ComparisonOperator.GE, "100", null); - header.setNumberOfConditionalFormats(3); - CellRangeAddress[] cellRanges = { - new CellRangeAddress(0,1,0,0), - new CellRangeAddress(0,1,2,2), - }; - header.setCellRanges(cellRanges); - recs.add(header); - recs.add(rule1); - recs.add(rule2); - recs.add(rule3); - CFRecordsAggregate record; - record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0)); + List recs = new ArrayList(); + CFHeaderBase header = new CFHeaderRecord(); + CFRuleBase rule1 = CFRuleRecord.create(sheet, "7"); + CFRuleBase rule2 = CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "2", "5"); + CFRuleBase rule3 = CFRuleRecord.create(sheet, ComparisonOperator.GE, "100", null); + header.setNumberOfConditionalFormats(3); + CellRangeAddress[] cellRanges = { + new CellRangeAddress(0,1,0,0), + new CellRangeAddress(0,1,2,2), + }; + header.setCellRanges(cellRanges); + recs.add(header); + recs.add(rule1); + recs.add(rule2); + recs.add(rule3); + CFRecordsAggregate record; + record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0)); - // Serialize - byte [] serializedRecord = new byte[record.getRecordSize()]; - record.serialize(0, serializedRecord); - InputStream in = new ByteArrayInputStream(serializedRecord); + // Serialize + byte [] serializedRecord = new byte[record.getRecordSize()]; + record.serialize(0, serializedRecord); + InputStream in = new ByteArrayInputStream(serializedRecord); - //Parse - recs = RecordFactory.createRecords(in); + //Parse + recs = RecordFactory.createRecords(in); - // Verify - assertNotNull(recs); - assertEquals(4, recs.size()); + // Verify + assertNotNull(recs); + assertEquals(4, recs.size()); - header = (CFHeaderRecord)recs.get(0); - rule1 = (CFRuleRecord)recs.get(1); - rule2 = (CFRuleRecord)recs.get(2); - rule3 = (CFRuleRecord)recs.get(3); - cellRanges = header.getCellRanges(); + header = (CFHeaderRecord)recs.get(0); + rule1 = (CFRuleRecord)recs.get(1); + rule2 = (CFRuleRecord)recs.get(2); + rule3 = (CFRuleRecord)recs.get(3); + cellRanges = header.getCellRanges(); - assertEquals(2, cellRanges.length); - assertEquals(3, header.getNumberOfConditionalFormats()); + assertEquals(2, cellRanges.length); + assertEquals(3, header.getNumberOfConditionalFormats()); - record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0)); + record = CFRecordsAggregate.createCFAggregate(new RecordStream(recs, 0)); - record = record.cloneCFAggregate(); + record = record.cloneCFAggregate(); - assertNotNull(record.getHeader()); - assertEquals(3,record.getNumberOfRules()); + assertNotNull(record.getHeader()); + assertEquals(3,record.getNumberOfRules()); - header = record.getHeader(); - rule1 = record.getRule(0); - rule2 = record.getRule(1); - rule3 = record.getRule(2); - cellRanges = header.getCellRanges(); + header = record.getHeader(); + rule1 = record.getRule(0); + rule2 = record.getRule(1); + rule3 = record.getRule(2); + cellRanges = header.getCellRanges(); - assertEquals(2, cellRanges.length); - assertEquals(3, header.getNumberOfConditionalFormats()); - } - - /** - * Make sure that the CF Header record is properly updated with the number of rules - */ - public void testNRules() { - HSSFWorkbook workbook = new HSSFWorkbook(); + assertEquals(2, cellRanges.length); + assertEquals(3, header.getNumberOfConditionalFormats()); + } + + /** + * Make sure that the CF Header record is properly updated with the number of rules + */ + public void testNRules() { + HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(); - CellRangeAddress[] cellRanges = { - new CellRangeAddress(0,1,0,0), - new CellRangeAddress(0,1,2,2), - }; - CFRuleRecord[] rules = { - CFRuleRecord.create(sheet, "7"), - CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "2", "5"), - }; - CFRecordsAggregate agg = new CFRecordsAggregate(cellRanges, rules); - byte[] serializedRecord = new byte[agg.getRecordSize()]; - agg.serialize(0, serializedRecord); - - int nRules = LittleEndian.getUShort(serializedRecord, 4); - if (nRules == 0) { - throw new AssertionFailedError("Identified bug 45682 b"); - } - assertEquals(rules.length, nRules); - } + CellRangeAddress[] cellRanges = { + new CellRangeAddress(0,1,0,0), + new CellRangeAddress(0,1,2,2), + }; + CFRuleRecord[] rules = { + CFRuleRecord.create(sheet, "7"), + CFRuleRecord.create(sheet, ComparisonOperator.BETWEEN, "2", "5"), + }; + CFRecordsAggregate agg = new CFRecordsAggregate(cellRanges, rules); + byte[] serializedRecord = new byte[agg.getRecordSize()]; + agg.serialize(0, serializedRecord); + + int nRules = LittleEndian.getUShort(serializedRecord, 4); + if (nRules == 0) { + throw new AssertionFailedError("Identified bug 45682 b"); + } + assertEquals(rules.length, nRules); + } + + public void testCantMixTypes() { + HSSFWorkbook workbook = new HSSFWorkbook(); + HSSFSheet sheet = workbook.createSheet(); + CellRangeAddress[] cellRanges = { + new CellRangeAddress(0,1,0,0), + new CellRangeAddress(0,1,2,2), + }; + CFRuleBase[] rules = { + CFRuleRecord.create(sheet, "7"), + CFRule12Record.create(sheet, ComparisonOperator.BETWEEN, "2", "5"), + }; + try { + new CFRecordsAggregate(cellRanges, rules); + fail("Shouldn't be able to mix between types"); + } catch (IllegalArgumentException e) {} + + + rules = new CFRuleBase[] { CFRuleRecord.create(sheet, "7") }; + CFRecordsAggregate agg = new CFRecordsAggregate(cellRanges, rules); + + try { + agg.addRule(CFRule12Record.create(sheet, "7")); + fail("Shouldn't be able to mix between types"); + } catch (IllegalArgumentException e) {} + } } diff --git a/src/testcases/org/apache/poi/hssf/record/crypto/TestBiff8DecryptingStream.java b/src/testcases/org/apache/poi/hssf/record/crypto/TestBiff8DecryptingStream.java index 9d9c04417..6c8cd0177 100644 --- a/src/testcases/org/apache/poi/hssf/record/crypto/TestBiff8DecryptingStream.java +++ b/src/testcases/org/apache/poi/hssf/record/crypto/TestBiff8DecryptingStream.java @@ -96,9 +96,21 @@ public final class TestBiff8DecryptingStream { } public void confirmShort(int expVal) { - cmp(HexDump.shortToHex(expVal), HexDump.shortToHex(_bds.readUShort())); + cmp(HexDump.shortToHex(expVal), HexDump.shortToHex(_bds.readShort())); } + public void confirmUShort(int expVal) { + cmp(HexDump.shortToHex(expVal), HexDump.shortToHex(_bds.readUShort())); + } + + public short readShort() { + return _bds.readShort(); + } + + public int readUShort() { + return _bds.readUShort(); + } + public void confirmInt(int expVal) { cmp(HexDump.intToHex(expVal), HexDump.intToHex(_bds.readInt())); } @@ -106,7 +118,7 @@ public final class TestBiff8DecryptingStream { public void confirmLong(long expVal) { cmp(HexDump.longToHex(expVal), HexDump.longToHex(_bds.readLong())); } - + private void cmp(char[] exp, char[] act) { if (Arrays.equals(exp, act)) { return; @@ -166,6 +178,15 @@ public final class TestBiff8DecryptingStream { st.rollForward(0x0C04, 0x0FF8); st.confirmLong(0x6AA2D5F6B975D10CL); st.confirmLong(0x34248ADF7ED4F029L); + // check for signed/unsigned shorts #58069 + st.rollForward(0x1008, 0x7213); + st.confirmUShort(0xFFFF); + st.rollForward(0x7215, 0x1B9AD); + st.confirmShort(-1); + st.rollForward(0x1B9AF, 0x37D99); + assertEquals(0xFFFF, st.readUShort()); + st.rollForward(0x37D9B, 0x4A6F2); + assertEquals(-1, st.readShort()); st.assertNoErrors(); } @@ -229,7 +250,7 @@ public final class TestBiff8DecryptingStream { st.confirmData("01 C2 4E 55"); // first 4 bytes in next block st.assertNoErrors(); } - + private static StreamTester createStreamTester(int mockStreamStartVal, String keyDigestHex, int expectedFirstInt) { return new StreamTester(new MockStream(mockStreamStartVal), keyDigestHex, expectedFirstInt); } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/StreamUtility.java b/src/testcases/org/apache/poi/hssf/usermodel/StreamUtility.java index b9f39a03c..06aa0b84b 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/StreamUtility.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/StreamUtility.java @@ -82,7 +82,7 @@ public final class StreamUtility { private static int[] diffInternal(InputStream isA, InputStream isB, int[] allowableDifferenceRegions) throws IOException { int offset = 0; - List temp = new ArrayList(); + List temp = new ArrayList(); while (true) { int b = isA.read(); int b2 = isB.read(); @@ -114,7 +114,7 @@ public final class StreamUtility { return false; } - private static int[] toPrimitiveIntArray(List temp) { + private static int[] toPrimitiveIntArray(List temp) { int nItems = temp.size(); if(nItems < 1) { return null; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java index 873647805..af6e8bb03 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java @@ -32,6 +32,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -58,6 +59,7 @@ import org.apache.poi.hssf.record.aggregates.RecordAggregate; import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.formula.ptg.DeletedArea3DPtg; @@ -71,6 +73,7 @@ import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.util.TempFile; import org.junit.Ignore; import org.junit.Test; @@ -108,9 +111,12 @@ public final class TestBugs extends BaseTestBugzillaIssues { File file; try { file = TempFile.createTempFile(simpleFileName + "#", ".xls"); - FileOutputStream out = new FileOutputStream(file); - wb.write(out); - out.close(); + OutputStream out = new FileOutputStream(file); + try { + wb.write(out); + } finally { + out.close(); + } } catch (IOException e) { throw new RuntimeException(e); } @@ -176,7 +182,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { cell = row.createCell(3); // Write test - cell.setCellType(HSSFCell.CELL_TYPE_STRING); + cell.setCellType(Cell.CELL_TYPE_STRING); setCellText(cell, "a test"); // change existing numeric cell value @@ -289,7 +295,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFCell d1 = w.getSheetAt(0).getRow(3).getCell(0); HSSFCell d2 = w.getSheetAt(0).getRow(3).getCell(1); - if (false) { + /* // THAI code page System.out.println("a1="+unicodeString(a1)); System.out.println("a2="+unicodeString(a2)); @@ -302,7 +308,8 @@ public final class TestBugs extends BaseTestBugzillaIssues { // US+THAI System.out.println("d1="+unicodeString(d1)); System.out.println("d2="+unicodeString(d2)); - } + */ + confirmSameCellText(a1, a2); confirmSameCellText(b1, b2); confirmSameCellText(c1, c2); @@ -334,7 +341,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals(a.getRichStringCellValue().getString(), b.getRichStringCellValue().getString()); } - private static String unicodeString(HSSFCell cell) { + /*private static String unicodeString(HSSFCell cell) { String ss = cell.getRichStringCellValue().getString(); char s[] = ss.toCharArray(); StringBuffer sb = new StringBuffer(); @@ -342,7 +349,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { sb.append("\\u").append(Integer.toHexString(s[x])); } return sb.toString(); - } + }*/ /** Error in opening wb*/ @Test @@ -457,7 +464,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFRow row = sheet.getRow(i); if (row != null) { HSSFCell cell = row .getCell(0); - assertEquals(HSSFCell.CELL_TYPE_STRING, cell.getCellType()); + assertEquals(Cell.CELL_TYPE_STRING, cell.getCellType()); count++; } } @@ -884,7 +891,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { List objects = wb.getAllEmbeddedObjects(); assertEquals(1, objects.size()); - HSSFObjectData obj = (HSSFObjectData)objects.get(0); + HSSFObjectData obj = objects.get(0); assertNotNull(obj); // Peek inside the underlying record @@ -973,9 +980,10 @@ public final class TestBugs extends BaseTestBugzillaIssues { /** * Test that fonts get added properly + * @throws IOException */ @Test - public void bug45338() { + public void bug45338() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); assertEquals(4, wb.getNumberOfFonts()); @@ -1054,6 +1062,8 @@ public final class TestBugs extends BaseTestBugzillaIssues { "Thingy", false, true, (short)2, (byte)2 ) ); + + wb.close(); } /** @@ -1145,13 +1155,13 @@ public final class TestBugs extends BaseTestBugzillaIssues { } private static void confirmCachedValue(double expectedValue, HSSFCell cell) { - assertEquals(HSSFCell.CELL_TYPE_FORMULA, cell.getCellType()); - assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType()); + assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType()); + assertEquals(Cell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType()); assertEquals(expectedValue, cell.getNumericCellValue(), 0.0); } private static void confirmCachedValue(String expectedValue, HSSFCell cell) { - assertEquals(HSSFCell.CELL_TYPE_FORMULA, cell.getCellType()); - assertEquals(HSSFCell.CELL_TYPE_STRING, cell.getCachedFormulaResultType()); + assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType()); + assertEquals(Cell.CELL_TYPE_STRING, cell.getCachedFormulaResultType()); assertEquals(expectedValue, cell.getRichStringCellValue().getString()); } @@ -1198,9 +1208,10 @@ public final class TestBugs extends BaseTestBugzillaIssues { /** * People are all getting confused about the last * row and cell number + * @throws IOException */ @Test - public void bug30635() { + public void bug30635() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet s = wb.createSheet(); @@ -1243,6 +1254,8 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals(0, r.getFirstCellNum()); assertEquals(5, r.getLastCellNum()); // last cell # + 1 assertEquals(3, r.getPhysicalNumberOfCells()); + + wb.close(); } /** @@ -1261,7 +1274,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { s = wb.getSheet("OneVariable Table Completed"); r = s.getRow(3); c = r.getCell(4); - assertEquals(HSSFCell.CELL_TYPE_FORMULA, c.getCellType()); + assertEquals(Cell.CELL_TYPE_FORMULA, c.getCellType()); // TODO - check the formula once tables and // arrays are properly supported @@ -1271,7 +1284,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { s = wb.getSheet("TwoVariable Table Example"); r = s.getRow(3); c = r.getCell(4); - assertEquals(HSSFCell.CELL_TYPE_FORMULA, c.getCellType()); + assertEquals(Cell.CELL_TYPE_FORMULA, c.getCellType()); // TODO - check the formula once tables and // arrays are properly supported @@ -1324,7 +1337,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertTrue(wb.isSheetVeryHidden(2)); // Change 0 to be very hidden, and re-load - wb.setSheetHidden(0, HSSFWorkbook.SHEET_STATE_VERY_HIDDEN); + wb.setSheetHidden(0, Workbook.SHEET_STATE_VERY_HIDDEN); HSSFWorkbook nwb = writeOutAndReadBack(wb); @@ -1565,10 +1578,26 @@ public final class TestBugs extends BaseTestBugzillaIssues { * (is an excel 95 file though) */ @Test - public void bug46904() { + public void bug46904() throws Exception { try { - openSample("46904.xls"); - fail(); + OPOIFSFileSystem fs = new OPOIFSFileSystem( + HSSFITestDataProvider.instance.openWorkbookStream("46904.xls")); + new HSSFWorkbook(fs.getRoot(), false).close(); + fail("Should catch exception here"); + } catch(OldExcelFormatException e) { + assertTrue(e.getMessage().startsWith( + "The supplied spreadsheet seems to be Excel" + )); + } + try { + NPOIFSFileSystem fs = new NPOIFSFileSystem( + HSSFITestDataProvider.instance.openWorkbookStream("46904.xls")); + try { + new HSSFWorkbook(fs.getRoot(), false).close(); + fail("Should catch exception here"); + } finally { + fs.close(); + } } catch(OldExcelFormatException e) { assertTrue(e.getMessage().startsWith( "The supplied spreadsheet seems to be Excel" @@ -1634,11 +1663,11 @@ public final class TestBugs extends BaseTestBugzillaIssues { public void bug47251() { // Firstly, try with one that triggers on InterfaceHdrRecord openSample("47251.xls"); - + // Now with one that triggers on NoteRecord openSample("47251_1.xls"); } - + /** * Round trip a file with an unusual UnicodeString/ExtRst record parts */ @@ -1646,35 +1675,35 @@ public final class TestBugs extends BaseTestBugzillaIssues { public void bug47847() throws Exception { HSSFWorkbook wb = openSample("47847.xls"); assertEquals(3, wb.getNumberOfSheets()); - + // Find the SST record UnicodeString withExt = wb.getWorkbook().getSSTString(0); UnicodeString withoutExt = wb.getWorkbook().getSSTString(31); - + assertEquals("O:Alloc:Qty", withExt.getString()); assertTrue((withExt.getOptionFlags() & 0x0004) == 0x0004); - + assertEquals("RT", withoutExt.getString()); assertTrue((withoutExt.getOptionFlags() & 0x0004) == 0x0000); - + // Something about continues... - + // Write out and re-read wb = writeOutAndReadBack(wb); assertEquals(3, wb.getNumberOfSheets()); - + // Check it's the same now withExt = wb.getWorkbook().getSSTString(0); withoutExt = wb.getWorkbook().getSSTString(31); - + assertEquals("O:Alloc:Qty", withExt.getString()); assertTrue((withExt.getOptionFlags() & 0x0004) == 0x0004); - + assertEquals("RT", withoutExt.getString()); assertTrue((withoutExt.getOptionFlags() & 0x0004) == 0x0000); } - + /** * Problem with cloning a sheet with a chart * contained in it. @@ -1683,21 +1712,21 @@ public final class TestBugs extends BaseTestBugzillaIssues { public void bug49096() throws Exception { HSSFWorkbook wb = openSample("49096.xls"); assertEquals(1, wb.getNumberOfSheets()); - + assertNotNull(wb.getSheetAt(0)); wb.cloneSheet(0); assertEquals(2, wb.getNumberOfSheets()); - + wb = writeOutAndReadBack(wb); assertEquals(2, wb.getNumberOfSheets()); } - + /** - * Newly created sheets need to get a + * Newly created sheets need to get a * proper TabID, otherwise print setup * gets confused on them. * Also ensure that print setup refs are - * by reference not value + * by reference not value */ @Test public void bug46664() throws Exception { @@ -1719,9 +1748,9 @@ public final class TestBugs extends BaseTestBugzillaIssues { 0, //start row 0 //end row ); - + wb = writeOutAndReadBack(wb); - + // Ensure the tab index TabIdRecord tr = null; for(Record r : wb.getWorkbook().getRecords()) { @@ -1732,108 +1761,106 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertNotNull(tr); assertEquals(1, tr._tabids.length); assertEquals(0, tr._tabids[0]); - + // Ensure the print setup assertEquals("new_sheet!$A$1:$C$1", wb.getPrintArea(0)); assertEquals("new_sheet!$A$1:$C$1", wb.getName("Print_Area").getRefersToFormula()); - + // Needs reference not value NameRecord nr = wb.getWorkbook().getNameRecord( wb.getNameIndex("Print_Area") - ); + ); assertEquals("Print_Area", nr.getNameText()); assertEquals(1, nr.getNameDefinition().length); assertEquals( - "new_sheet!$A$1:$C$1", + "new_sheet!$A$1:$C$1", ((Area3DPtg)nr.getNameDefinition()[0]).toFormulaString(HSSFEvaluationWorkbook.create(wb)) ); assertEquals('R', nr.getNameDefinition()[0].getRVAType()); } - + /** - * Problems with formula references to + * Problems with formula references to * sheets via URLs */ @Test public void bug45970() throws Exception { HSSFWorkbook wb = openSample("FormulaRefs.xls"); assertEquals(3, wb.getNumberOfSheets()); - + HSSFSheet s = wb.getSheetAt(0); HSSFRow row; - + row = s.getRow(0); assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(1).getCellType()); assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0); - + row = s.getRow(1); assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); assertEquals("B1", row.getCell(1).getCellFormula()); assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0); - + row = s.getRow(2); assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); assertEquals("Sheet1!B1", row.getCell(1).getCellFormula()); assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0); - + row = s.getRow(3); assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); assertEquals("[Formulas2.xls]Sheet1!B2", row.getCell(1).getCellFormula()); assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0); - + row = s.getRow(4); assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); assertEquals("'[$http://gagravarr.org/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula()); assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0); - + // Change 4 row.getCell(1).setCellFormula("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2"); row.getCell(1).setCellValue(123.0); - + // Add 5 row = s.createRow(5); row.createCell(1, Cell.CELL_TYPE_FORMULA); row.getCell(1).setCellFormula("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1"); row.getCell(1).setCellValue(234.0); - - + + // Re-test wb = writeOutAndReadBack(wb); s = wb.getSheetAt(0); - + row = s.getRow(0); assertEquals(Cell.CELL_TYPE_NUMERIC, row.getCell(1).getCellType()); assertEquals(112.0, row.getCell(1).getNumericCellValue(),0); - + row = s.getRow(1); assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); assertEquals("B1", row.getCell(1).getCellFormula()); assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0); - + row = s.getRow(2); assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); assertEquals("Sheet1!B1", row.getCell(1).getCellFormula()); assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0); - + row = s.getRow(3); assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); assertEquals("[Formulas2.xls]Sheet1!B2", row.getCell(1).getCellFormula()); assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0); - + // TODO - Fix these so they work... - if(1==2) { - row = s.getRow(4); - assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); - assertEquals("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.getCell(1).getCellFormula()); - assertEquals(123.0, row.getCell(1).getNumericCellValue(), 0); - - row = s.getRow(5); - assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); - assertEquals("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula()); - assertEquals(234.0, row.getCell(1).getNumericCellValue(), 0); - } + /*row = s.getRow(4); + assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); + assertEquals("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.getCell(1).getCellFormula()); + assertEquals(123.0, row.getCell(1).getNumericCellValue(), 0); + + row = s.getRow(5); + assertEquals(Cell.CELL_TYPE_FORMULA, row.getCell(1).getCellType()); + assertEquals("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula()); + assertEquals(234.0, row.getCell(1).getNumericCellValue(), 0);*/ } - + /** * Test for a file with NameRecord with NameCommentRecord comments */ @@ -1842,26 +1869,26 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFWorkbook wb = openSample("49185.xls"); Name name = wb.getName("foobarName"); assertEquals("This is a comment", name.getComment()); - + // Rename the name, comment comes with it name.setNameName("ChangedName"); assertEquals("This is a comment", name.getComment()); - + // Save and re-check wb = writeOutAndReadBack(wb); name = wb.getName("ChangedName"); assertEquals("This is a comment", name.getComment()); - + // Now try to change it name.setComment("Changed Comment"); assertEquals("Changed Comment", name.getComment()); - + // Save and re-check wb = writeOutAndReadBack(wb); name = wb.getName("ChangedName"); assertEquals("Changed Comment", name.getComment()); } - + /** * Vertically aligned text */ @@ -1872,11 +1899,11 @@ public final class TestBugs extends BaseTestBugzillaIssues { Row r = s.getRow(0); Cell rotated = r.getCell(0); Cell normal = r.getCell(1); - + // Check the current ones assertEquals(0, normal.getCellStyle().getRotation()); assertEquals(0xff, rotated.getCellStyle().getRotation()); - + // Add a new style, also rotated CellStyle cs = wb.createCellStyle(); cs.setRotation((short)0xff); @@ -1884,22 +1911,22 @@ public final class TestBugs extends BaseTestBugzillaIssues { nc.setCellValue("New Rotated Text"); nc.setCellStyle(cs); assertEquals(0xff, nc.getCellStyle().getRotation()); - + // Write out and read back wb = writeOutAndReadBack(wb); - + // Re-check s = wb.getSheetAt(0); r = s.getRow(0); rotated = r.getCell(0); normal = r.getCell(1); nc = r.getCell(2); - + assertEquals(0, normal.getCellStyle().getRotation()); assertEquals(0xff, rotated.getCellStyle().getRotation()); assertEquals(0xff, nc.getCellStyle().getRotation()); } - + /** * Setting the user style name on custom styles */ @@ -1909,26 +1936,26 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFSheet s = wb.createSheet("Test"); HSSFRow r = s.createRow(0); HSSFCell c = r.createCell(0); - + HSSFCellStyle cs1 = wb.createCellStyle(); HSSFCellStyle cs2 = wb.createCellStyle(); HSSFCellStyle cs3 = wb.createCellStyle(); - + assertEquals(21, cs1.getIndex()); cs1.setUserStyleName("Testing"); - + assertEquals(22, cs2.getIndex()); cs2.setUserStyleName("Testing 2"); - + assertEquals(23, cs3.getIndex()); cs3.setUserStyleName("Testing 3"); - + // Set one c.setCellStyle(cs1); - + // Write out and read back wb = writeOutAndReadBack(wb); - + // Re-check assertEquals("Testing", wb.getCellStyleAt((short)21).getUserStyleName()); assertEquals("Testing 2", wb.getCellStyleAt((short)22).getUserStyleName()); @@ -1941,7 +1968,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { short numCellStyles = wb.getNumCellStyles(); List namedStyles = Arrays.asList( "20% - Accent1", "20% - Accent2", "20% - Accent3", "20% - Accent4", "20% - Accent5", - "20% - Accent6", "40% - Accent1", "40% - Accent2", "40% - Accent3", "40% - Accent4", + "20% - Accent6", "40% - Accent1", "40% - Accent2", "40% - Accent3", "40% - Accent4", "40% - Accent5", "40% - Accent6", "60% - Accent1", "60% - Accent2", "60% - Accent3", "60% - Accent4", "60% - Accent5", "60% - Accent6", "Accent1", "Accent2", "Accent3", "Accent4", "Accent5", "Accent6", "Bad", "Calculation", "Check Cell", "Explanatory Text", @@ -1957,19 +1984,19 @@ public final class TestBugs extends BaseTestBugzillaIssues { } } assertTrue(namedStyles.containsAll(collecteddStyles)); - } - + } + /** * Regression with the PageSettingsBlock */ @Test public void bug49931() throws Exception { HSSFWorkbook wb = openSample("49931.xls"); - + assertEquals(1, wb.getNumberOfSheets()); assertEquals("Foo", wb.getSheetAt(0).getRow(0).getCell(0).getRichStringCellValue().toString()); } - + /** * Missing left/right/centre options on a footer */ @@ -1984,7 +2011,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals("Left text should be empty", "", f.getLeft()); assertEquals("Right text should be empty", "", f.getRight()); assertEquals( - "Center text should contain the illegal value", + "Center text should contain the illegal value", "BlahBlah blah blah ", f.getCenter() ); } @@ -2003,12 +2030,13 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFWorkbook wb = openSample("50426.xls"); writeOutAndReadBack(wb); } - + /** * Last row number when shifting rows + * @throws IOException */ @Test - public void bug50416LastRowNumber() { + public void bug50416LastRowNumber() throws IOException { // Create the workbook with 1 sheet which contains 3 rows HSSFWorkbook workbook = new HSSFWorkbook(); Sheet sheet = workbook.createSheet("Bug50416"); @@ -2021,10 +2049,10 @@ public final class TestBugs extends BaseTestBugzillaIssues { Row row3 = sheet.createRow(2); Cell cellA_3 = row3.createCell(0,Cell.CELL_TYPE_STRING); cellA_3.setCellValue("Cell A,3"); - + // Test the last Row number it currently correct assertEquals(2, sheet.getLastRowNum()); - + // Shift the first row to the end sheet.shiftRows(0, 0, 3); assertEquals(3, sheet.getLastRowNum()); @@ -2032,7 +2060,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals("Cell A,2", sheet.getRow(1).getCell(0).getStringCellValue()); assertEquals("Cell A,3", sheet.getRow(2).getCell(0).getStringCellValue()); assertEquals("Cell A,1", sheet.getRow(3).getCell(0).getStringCellValue()); - + // Shift the 2nd row up to the first one sheet.shiftRows(1, 1, -1); assertEquals(3, sheet.getLastRowNum()); @@ -2048,17 +2076,19 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals("Cell A,1", sheet.getRow(1).getCell(0).getStringCellValue()); assertEquals("Cell A,3", sheet.getRow(2).getCell(0).getStringCellValue()); assertEquals(-1, sheet.getRow(3).getLastCellNum()); - + // Now zap the empty 4th row - won't do anything sheet.removeRow(sheet.getRow(3)); - + // Test again the last row number which should be 2 assertEquals(2, sheet.getLastRowNum()); assertEquals("Cell A,2", sheet.getRow(0).getCell(0).getStringCellValue()); assertEquals("Cell A,1", sheet.getRow(1).getCell(0).getStringCellValue()); assertEquals("Cell A,3", sheet.getRow(2).getCell(0).getStringCellValue()); + + workbook.close(); } - + /** * If you send a file between Excel and OpenOffice enough, something * will turn the "General" format into "GENERAL" @@ -2070,7 +2100,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFRow r17 = s.getRow(16); HSSFRow r18 = s.getRow(17); HSSFDataFormatter df = new HSSFDataFormatter(); - + assertEquals(10.0, r17.getCell(1).getNumericCellValue(), 0); assertEquals(20.0, r17.getCell(2).getNumericCellValue(), 0); assertEquals(20.0, r17.getCell(3).getNumericCellValue(), 0); @@ -2080,7 +2110,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals("10", df.formatCellValue(r17.getCell(1))); assertEquals("20", df.formatCellValue(r17.getCell(2))); assertEquals("20", df.formatCellValue(r17.getCell(3))); - + assertEquals(16.0, r18.getCell(1).getNumericCellValue(), 0); assertEquals(35.0, r18.getCell(2).getNumericCellValue(), 0); assertEquals(123.0, r18.getCell(3).getNumericCellValue(), 0); @@ -2091,7 +2121,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals("35", df.formatCellValue(r18.getCell(2))); assertEquals("123", df.formatCellValue(r18.getCell(3))); } - + /** * A protected sheet with comments, when written out by * POI, ends up upsetting excel. @@ -2100,32 +2130,32 @@ public final class TestBugs extends BaseTestBugzillaIssues { */ @Test public void bug50833() throws Exception { - Biff8EncryptionKey.setCurrentUserPassword(null); - + Biff8EncryptionKey.setCurrentUserPassword(null); + HSSFWorkbook wb = openSample("50833.xls"); HSSFSheet s = wb.getSheetAt(0); assertEquals("Sheet1", s.getSheetName()); assertEquals(false, s.getProtect()); - + HSSFCell c = s.getRow(0).getCell(0); assertEquals("test cell value", c.getRichStringCellValue().getString()); - + HSSFComment cmt = c.getCellComment(); assertNotNull(cmt); assertEquals("Robert Lawrence", cmt.getAuthor()); assertEquals("Robert Lawrence:\ntest comment", cmt.getString().getString()); - + // Reload wb = writeOutAndReadBack(wb); s = wb.getSheetAt(0); c = s.getRow(0).getCell(0); - + // Re-check the comment cmt = c.getCellComment(); assertNotNull(cmt); assertEquals("Robert Lawrence", cmt.getAuthor()); assertEquals("Robert Lawrence:\ntest comment", cmt.getString().getString()); - + // TODO Identify what excel doesn't like, and check for that } @@ -2140,26 +2170,26 @@ public final class TestBugs extends BaseTestBugzillaIssues { /** * The spec says that ChartEndObjectRecord has 6 reserved - * bytes on the end, but we sometimes find files without... + * bytes on the end, but we sometimes find files without... */ @Test public void bug50939() throws Exception { HSSFWorkbook wb = openSample("50939.xls"); assertEquals(2, wb.getNumberOfSheets()); } - + @Test public void bug49219() throws Exception { HSSFWorkbook wb = openSample("49219.xls"); assertEquals(1, wb.getNumberOfSheets()); assertEquals("DGATE", wb.getSheetAt(0).getRow(1).getCell(0).getStringCellValue()); } - + @Test public void bug48968() throws Exception { HSSFWorkbook wb = openSample("48968.xls"); assertEquals(1, wb.getNumberOfSheets()); - + DataFormatter fmt = new DataFormatter(); // Check the dates @@ -2172,7 +2202,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { // There is no such thing as 00/01/1900... assertEquals("00/01/1900 06:14:24", s.getRow(21).getCell(3).getStringCellValue()); assertEquals("31/12/1899 06:14:24", fmt.formatCellValue(cell_d19000100)); - + // Check the cached values assertEquals("HOUR(A1)", s.getRow(5).getCell(0).getCellFormula()); assertEquals(11.0, s.getRow(5).getCell(0).getNumericCellValue(), 0); @@ -2180,7 +2210,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals(39.0, s.getRow(6).getCell(0).getNumericCellValue(), 0); assertEquals("SECOND(A1)", s.getRow(7).getCell(0).getCellFormula()); assertEquals(54.0, s.getRow(7).getCell(0).getNumericCellValue(), 0); - + // Re-evaulate and check HSSFFormulaEvaluator.evaluateAllFormulaCells(wb); assertEquals("HOUR(A1)", s.getRow(5).getCell(0).getCellFormula()); @@ -2189,11 +2219,11 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals(39.0, s.getRow(6).getCell(0).getNumericCellValue(), 0); assertEquals("SECOND(A1)", s.getRow(7).getCell(0).getCellFormula()); assertEquals(54.0, s.getRow(7).getCell(0).getNumericCellValue(), 0); - + // Push the time forward a bit and check double date = s.getRow(0).getCell(0).getNumericCellValue(); s.getRow(0).getCell(0).setCellValue(date + 1.26); - + HSSFFormulaEvaluator.evaluateAllFormulaCells(wb); assertEquals("HOUR(A1)", s.getRow(5).getCell(0).getCellFormula()); assertEquals(11.0+6.0, s.getRow(5).getCell(0).getNumericCellValue(), 0); @@ -2202,9 +2232,9 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals("SECOND(A1)", s.getRow(7).getCell(0).getCellFormula()); assertEquals(54.0+24.0-60, s.getRow(7).getCell(0).getNumericCellValue(), 0); } - + /** - * Mixture of Ascii and Unicode strings in a + * Mixture of Ascii and Unicode strings in a * NameComment record */ @Test @@ -2214,25 +2244,25 @@ public final class TestBugs extends BaseTestBugzillaIssues { wb = writeOutAndReadBack(wb); assertEquals(1, wb.getNumberOfSheets()); } - + /** * File with exactly 256 data blocks (+header block) - * shouldn't break on POIFS loading + * shouldn't break on POIFS loading */ @SuppressWarnings("resource") @Test public void bug51461() throws Exception { byte[] data = HSSFITestDataProvider.instance.getTestDataFileContent("51461.xls"); - + HSSFWorkbook wbPOIFS = new HSSFWorkbook(new POIFSFileSystem( new ByteArrayInputStream(data)).getRoot(), false); HSSFWorkbook wbNPOIFS = new HSSFWorkbook(new NPOIFSFileSystem( new ByteArrayInputStream(data)).getRoot(), false); - + assertEquals(2, wbPOIFS.getNumberOfSheets()); assertEquals(2, wbNPOIFS.getNumberOfSheets()); } - + /** * Large row numbers and NPOIFS vs POIFS */ @@ -2240,22 +2270,22 @@ public final class TestBugs extends BaseTestBugzillaIssues { @Test public void bug51535() throws Exception { byte[] data = HSSFITestDataProvider.instance.getTestDataFileContent("51535.xls"); - + HSSFWorkbook wbPOIFS = new HSSFWorkbook(new POIFSFileSystem( new ByteArrayInputStream(data)).getRoot(), false); HSSFWorkbook wbNPOIFS = new HSSFWorkbook(new NPOIFSFileSystem( new ByteArrayInputStream(data)).getRoot(), false); - + for(HSSFWorkbook wb : new HSSFWorkbook[] {wbPOIFS, wbNPOIFS}) { assertEquals(3, wb.getNumberOfSheets()); - + // Check directly HSSFSheet s = wb.getSheetAt(0); assertEquals("Top Left Cell", s.getRow(0).getCell(0).getStringCellValue()); assertEquals("Top Right Cell", s.getRow(0).getCell(255).getStringCellValue()); assertEquals("Bottom Left Cell", s.getRow(65535).getCell(0).getStringCellValue()); assertEquals("Bottom Right Cell", s.getRow(65535).getCell(255).getStringCellValue()); - + // Extract and check ExcelExtractor ex = new ExcelExtractor(wb); String text = ex.getText(); @@ -2272,7 +2302,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFWorkbook wb = openSample("51670.xls"); writeOutAndReadBack(wb); } - + /** * Sum across multiple workbooks * eg =SUM($Sheet2.A1:$Sheet3.A1) @@ -2282,15 +2312,15 @@ public final class TestBugs extends BaseTestBugzillaIssues { public void test48703() { HSSFWorkbook wb = openSample("48703.xls"); assertEquals(3, wb.getNumberOfSheets()); - + // Check reading the formula Sheet sheet = wb.getSheetAt(0); Row r = sheet.getRow(0); Cell c = r.getCell(0); - + assertEquals("SUM(Sheet2!A1:Sheet3!A1)", c.getCellFormula()); assertEquals(4.0, c.getNumericCellValue(), 0); - + // Check the evaluated result HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(wb); eval.evaluateFormulaCell(c); @@ -2328,7 +2358,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { // make sure we are still readable writeOutAndReadBack(workbook); } - + /** * Note - part of this test is still failing, see * {@link TestUnfixedBugs#test49612()} @@ -2353,7 +2383,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals("evaluating d1", 30.0, eval.evaluate(d1).getNumberValue(), 0.001); assertEquals("evaluating e1", 30.0, eval.evaluate(e1).getNumberValue(), 0.001); } - + @Test public void bug51675(){ final List list = new ArrayList(); @@ -2362,6 +2392,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { InternalSheet ish = HSSFTestHelper.getSheetForTest(sh); PageSettingsBlock psb = (PageSettingsBlock) ish.getRecords().get(13); psb.visitContainedRecords(new RecordAggregate.RecordVisitor() { + @Override public void visitRecord(Record r) { list.add(r.getSid()); } @@ -2369,27 +2400,32 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertTrue(list.get(list.size()-1).intValue() == UnknownRecord.BITMAP_00E9); assertTrue(list.get(list.size()-2).intValue() == UnknownRecord.HEADER_FOOTER_089C); } - + @Test - public void bug52272(){ + public void bug52272() throws IOException{ HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet(); HSSFPatriarch p = sh.createDrawingPatriarch(); - + HSSFSimpleShape s = p.createSimpleShape(new HSSFClientAnchor()); s.setShapeType(HSSFSimpleShape.OBJECT_TYPE_LINE); HSSFSheet sh2 = wb.cloneSheet(0); assertNotNull(sh2.getDrawingPatriarch()); + + wb.close(); } @Test - public void bug53432(){ + public void bug53432() throws IOException{ Workbook wb = new HSSFWorkbook(); //or new HSSFWorkbook(); wb.addPicture(new byte[]{123,22}, Workbook.PICTURE_TYPE_JPEG); assertEquals(wb.getAllPictures().size(), 1); + wb.close(); + wb.close(); wb = new HSSFWorkbook(); + wb = writeOutAndReadBack((HSSFWorkbook) wb); assertEquals(wb.getAllPictures().size(), 0); wb.addPicture(new byte[]{123,22}, Workbook.PICTURE_TYPE_JPEG); @@ -2397,6 +2433,8 @@ public final class TestBugs extends BaseTestBugzillaIssues { wb = writeOutAndReadBack((HSSFWorkbook) wb); assertEquals(wb.getAllPictures().size(), 1); + + wb.close(); } @Test @@ -2448,7 +2486,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFSheet sheet = wb.getSheetAt(0); HSSFRow row = sheet.getRow(0); HSSFCellStyle rstyle = row.getRowStyle(); - assertEquals(rstyle.getBorderBottom(), HSSFCellStyle.BORDER_DOUBLE); + assertEquals(rstyle.getBorderBottom(), CellStyle.BORDER_DOUBLE); } @Test @@ -2460,7 +2498,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { } finally { Biff8EncryptionKey.setCurrentUserPassword(null); } - + // One using the only-recently-documented encryption header type 4, // and the RC4 CryptoAPI encryption header structure try { @@ -2484,7 +2522,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { } assertEquals(0, comments); } - + /** * Files initially created with Excel 2010 can have >3 CF rules */ @@ -2492,10 +2530,10 @@ public final class TestBugs extends BaseTestBugzillaIssues { public void bug56482() { HSSFWorkbook wb = openSample("56482.xls"); assertEquals(1, wb.getNumberOfSheets()); - + HSSFSheet sheet = wb.getSheetAt(0); HSSFSheetConditionalFormatting cf = sheet.getSheetConditionalFormatting(); - + assertEquals(5, cf.getNumConditionalFormattings()); } @@ -2507,11 +2545,11 @@ public final class TestBugs extends BaseTestBugzillaIssues { InputStream stream = new FileInputStream(file); try { POIFSFileSystem fs = new POIFSFileSystem(stream); - wb = new HSSFWorkbook(fs); + wb = new HSSFWorkbook(fs); } finally { stream.close(); } - + assertEquals(3, wb.getNumberOfSheets()); wb.removeSheetAt(0); assertEquals(2, wb.getNumberOfSheets()); @@ -2522,55 +2560,82 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals(1, wb.getNumberOfSheets()); wb.removeSheetAt(0); assertEquals(0, wb.getNumberOfSheets()); - + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); assertEquals(0, wb.getNumberOfSheets()); } - + + @Test + public void bug56325a() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("56325a.xls"); + + HSSFSheet sheet = wb.cloneSheet(2); + wb.setSheetName(3, "Clone 1"); + sheet.setRepeatingRows(CellRangeAddress.valueOf("2:3")); + wb.setPrintArea(3, "$A$4:$C$10"); + + sheet = wb.cloneSheet(2); + wb.setSheetName(4, "Clone 2"); + sheet.setRepeatingRows(CellRangeAddress.valueOf("2:3")); + wb.setPrintArea(4, "$A$4:$C$10"); + + wb.removeSheetAt(2); + + Workbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb); + assertEquals(4, wbBack.getNumberOfSheets()); + +// OutputStream fOut = new FileOutputStream("C:\\temp\\56325a.xls"); +// try { +// wb.write(fOut); +// } finally { +// fOut.close(); +// } + } + /** * Formulas which reference named ranges, either in other * sheets, or workbook scoped but in other workbooks. - * Used to fail with + * Used to fail with * java.lang.RuntimeException: Unexpected eval class (org.apache.poi.ss.formula.eval.NameXEval) */ @Test public void bug56737() throws IOException { Workbook wb = openSample("56737.xls"); - + // Check the named range definitions Name nSheetScope = wb.getName("NR_To_A1"); Name nWBScope = wb.getName("NR_Global_B2"); assertNotNull(nSheetScope); assertNotNull(nWBScope); - + assertEquals("Defines!$A$1", nSheetScope.getRefersToFormula()); assertEquals("Defines!$B$2", nWBScope.getRefersToFormula()); - + // Check the different kinds of formulas Sheet s = wb.getSheetAt(0); Cell cRefSName = s.getRow(1).getCell(3); Cell cRefWName = s.getRow(2).getCell(3); - + assertEquals("Defines!NR_To_A1", cRefSName.getCellFormula()); - + // TODO Correct this, so that the filename is shown too, see bug #56742 // This is what Excel itself shows //assertEquals("'56737.xls'!NR_Global_B2", cRefWName.getCellFormula()); // TODO This isn't right, but it's what we currently generate.... assertEquals("NR_Global_B2", cRefWName.getCellFormula()); - + // Try to evaluate them FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator(); assertEquals("Test A1", eval.evaluate(cRefSName).getStringValue()); assertEquals(142, (int)eval.evaluate(cRefWName).getNumberValue()); - + // Try to evaluate everything eval.evaluateAll(); } - + /** - * ClassCastException in HSSFOptimiser - StyleRecord cannot be cast to + * ClassCastException in HSSFOptimiser - StyleRecord cannot be cast to * ExtendedFormatRecord when removing un-used styles */ @Test @@ -2578,20 +2643,20 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFWorkbook workbook = new HSSFWorkbook( ); HSSFCellStyle style = workbook.createCellStyle(); HSSFCellStyle newStyle = workbook.createCellStyle(); - + HSSFSheet mySheet = workbook.createSheet(); HSSFRow row = mySheet.createRow(0); HSSFCell cell = row.createCell(0); - + // Use style cell.setCellStyle(style); // Switch to newStyle, style is now un-used cell.setCellStyle(newStyle); - + // Optimise HSSFOptimiser.optimiseCellStyles(workbook); } - + /** * Intersection formula ranges, eg =(C2:D3 D3:E4) */ @@ -2604,9 +2669,9 @@ public final class TestBugs extends BaseTestBugzillaIssues { Cell intF = s.getRow(2).getCell(0); assertEquals(Cell.CELL_TYPE_FORMULA, intF.getCellType()); assertEquals(Cell.CELL_TYPE_NUMERIC, intF.getCachedFormulaResultType()); - + assertEquals("(C2:D3 D3:E4)", intF.getCellFormula()); - + // Check we can evaluate it correctly FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator(); assertEquals("4.0", eval.evaluate(intF).formatAsString()); @@ -2618,7 +2683,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { Sheet s = wb.getSheetAt(0); for(int row = 0;row < 7;row++) { assertEquals("A$1+B$1", s.getRow(row).getCell(2).getCellFormula()); - } + } } /** @@ -2631,7 +2696,7 @@ public final class TestBugs extends BaseTestBugzillaIssues { assertEquals("International Communication Services SA", s.getRow(2).getCell(0).getStringCellValue()); assertEquals("Saudi Arabia-Riyadh", s.getRow(210).getCell(0).getStringCellValue()); } - + /** * Read, write, read for formulas point to cells in other files. * See {@link #bug46670()} for the main test, this just @@ -2644,20 +2709,20 @@ public final class TestBugs extends BaseTestBugzillaIssues { HSSFWorkbook wb; Sheet s; Cell c; - + // Expected values String refLocal = "'[refs/airport.xls]Sheet1'!$A$2"; String refHttp = "'[9http://www.principlesofeconometrics.com/excel/airline.xls]Sheet1'!$A$2"; - + // Check we can read them correctly wb = openSample("46670_local.xls"); s = wb.getSheetAt(0); assertEquals(refLocal, s.getRow(0).getCell(0).getCellFormula()); - + wb = openSample("46670_http.xls"); s = wb.getSheetAt(0); assertEquals(refHttp, s.getRow(0).getCell(0).getCellFormula()); - + // Now try to set them to the same values, and ensure that // they end up as they did before, even with a save and re-load wb = openSample("46670_local.xls"); @@ -2665,18 +2730,18 @@ public final class TestBugs extends BaseTestBugzillaIssues { c = s.getRow(0).getCell(0); c.setCellFormula(refLocal); assertEquals(refLocal, c.getCellFormula()); - + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); s = wb.getSheetAt(0); assertEquals(refLocal, s.getRow(0).getCell(0).getCellFormula()); - + wb = openSample("46670_http.xls"); s = wb.getSheetAt(0); c = s.getRow(0).getCell(0); c.setCellFormula(refHttp); assertEquals(refHttp, c.getCellFormula()); - + wb = HSSFTestDataSamples.writeOutAndReadBack(wb); s = wb.getSheetAt(0); assertEquals(refHttp, s.getRow(0).getCell(0).getCellFormula()); @@ -2687,4 +2752,69 @@ public final class TestBugs extends BaseTestBugzillaIssues { Workbook wb = openSample("57456.xls"); wb.close(); } + + @Test + public void test57163() throws IOException { + Workbook wb = openSample("57163.xls"); + + while (wb.getNumberOfSheets() > 1) { + wb.removeSheetAt(1); + } + wb.close(); + } + + @Test + public void test53109() throws IOException { + HSSFWorkbook wb = openSample("53109.xls"); + + Workbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb); + assertNotNull(wbBack); + + wb.close(); + } + + @Test + public void test53109a() throws IOException { + HSSFWorkbook wb = openSample("com.aida-tour.www_SPO_files_maldives%20august%20october.xls"); + + Workbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb); + assertNotNull(wbBack); + + wb.close(); + } + + @Test + public void test48043() throws IOException { + HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("56325a.xls"); + + wb.removeSheetAt(2); + wb.removeSheetAt(1); + + //Sheet s = wb.createSheet("sheetname"); + Sheet s = wb.getSheetAt(0); + Row row = s.createRow(0); + Cell cell = row.createCell(0); + + cell.setCellFormula( + "IF(AND(ISBLANK(A10)," + + "ISBLANK(B10)),\"\"," + + "CONCATENATE(A10,\"-\",B10))"); + + FormulaEvaluator eval = wb.getCreationHelper().createFormulaEvaluator(); + + eval.evaluateAll(); + + /*OutputStream out = new FileOutputStream("C:\\temp\\48043.xls"); + try { + wb.write(out); + } finally { + out.close(); + }*/ + + Workbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb); + assertNotNull(wbBack); + wbBack.close(); + + wb.close(); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java index 56a5bb162..6813baaa9 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestCloneSheet.java @@ -26,6 +26,7 @@ import junit.framework.TestCase; import org.apache.poi.ddf.EscherDgRecord; import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; import org.apache.poi.hssf.record.EscherAggregate; import org.apache.poi.ss.util.CellRangeAddress; @@ -37,19 +38,22 @@ import org.apache.poi.ss.util.CellRangeAddress; */ public final class TestCloneSheet extends TestCase { - public void testCloneSheetBasic(){ + public void testCloneSheetBasic() throws IOException{ HSSFWorkbook b = new HSSFWorkbook(); HSSFSheet s = b.createSheet("Test"); s.addMergedRegion(new CellRangeAddress(0, 1, 0, 1)); HSSFSheet clonedSheet = b.cloneSheet(0); assertEquals("One merged area", 1, clonedSheet.getNumMergedRegions()); + + b.close(); } /** * Ensures that pagebreak cloning works properly + * @throws IOException */ - public void testPageBreakClones() { + public void testPageBreakClones() throws IOException { HSSFWorkbook b = new HSSFWorkbook(); HSSFSheet s = b.createSheet("Test"); s.setRowBreak(3); @@ -62,6 +66,8 @@ public final class TestCloneSheet extends TestCase { s.removeRowBreak(3); assertTrue("Row 3 still should be broken", clone.isRowBroken(3)); + + b.close(); } public void testCloneSheetWithoutDrawings(){ @@ -121,16 +127,32 @@ public final class TestCloneSheet extends TestCase { HSSFSheet sh2 = wb.cloneSheet(0); HSSFPatriarch p2 = sh2.getDrawingPatriarch(); HSSFComment c2 = (HSSFComment) p2.getChildren().get(0); + + assertEquals(c.getString(), c2.getString()); + assertEquals(c.getRow(), c2.getRow()); + assertEquals(c.getColumn(), c2.getColumn()); + + // The ShapeId is not equal? + // assertEquals(c.getNoteRecord().getShapeId(), c2.getNoteRecord().getShapeId()); assertArrayEquals(c2.getTextObjectRecord().serialize(), c.getTextObjectRecord().serialize()); - assertArrayEquals(c2.getObjRecord().serialize(), c.getObjRecord().serialize()); - assertArrayEquals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize()); + + // ShapeId is different + CommonObjectDataSubRecord subRecord = (CommonObjectDataSubRecord) c2.getObjRecord().getSubRecords().get(0); + subRecord.setObjectId(1025); + assertArrayEquals(c2.getObjRecord().serialize(), c.getObjRecord().serialize()); + + // ShapeId is different + c2.getNoteRecord().setShapeId(1025); + assertArrayEquals(c2.getNoteRecord().serialize(), c.getNoteRecord().serialize()); //everything except spRecord.shapeId must be the same assertFalse(Arrays.equals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize())); EscherSpRecord sp = (EscherSpRecord) c2.getEscherContainer().getChild(0); sp.setShapeId(1025); assertArrayEquals(c2.getEscherContainer().serialize(), c.getEscherContainer().serialize()); + + wb.close(); } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java index cac444bae..2613e8cff 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestComment.java @@ -17,23 +17,30 @@ package org.apache.poi.hssf.usermodel; +import static org.junit.Assert.assertArrayEquals; + +import java.io.IOException; + import junit.framework.TestCase; + import org.apache.poi.ddf.EscherSpRecord; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.model.CommentShape; import org.apache.poi.hssf.model.HSSFTestModelHelper; -import org.apache.poi.hssf.record.*; - -import java.io.*; -import java.util.Arrays; +import org.apache.poi.hssf.record.CommonObjectDataSubRecord; +import org.apache.poi.hssf.record.EscherAggregate; +import org.apache.poi.hssf.record.NoteRecord; +import org.apache.poi.hssf.record.ObjRecord; +import org.apache.poi.hssf.record.TextObjectRecord; /** * @author Evgeniy Berlog * @date 26.06.12 */ +@SuppressWarnings("deprecation") public class TestComment extends TestCase { - public void testResultEqualsToAbstractShape() { + public void testResultEqualsToAbstractShape() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet(); HSSFPatriarch patriarch = sh.createDrawingPatriarch(); @@ -53,34 +60,35 @@ public class TestComment extends TestCase { byte[] actual = comment.getEscherContainer().getChild(0).serialize(); assertEquals(expected.length, actual.length); - assertTrue(Arrays.equals(expected, actual)); + assertArrayEquals(expected, actual); expected = commentShape.getSpContainer().getChild(2).serialize(); actual = comment.getEscherContainer().getChild(2).serialize(); assertEquals(expected.length, actual.length); - assertTrue(Arrays.equals(expected, actual)); + assertArrayEquals(expected, actual); expected = commentShape.getSpContainer().getChild(3).serialize(); actual = comment.getEscherContainer().getChild(3).serialize(); assertEquals(expected.length, actual.length); - assertTrue(Arrays.equals(expected, actual)); + assertArrayEquals(expected, actual); expected = commentShape.getSpContainer().getChild(4).serialize(); actual = comment.getEscherContainer().getChild(4).serialize(); assertEquals(expected.length, actual.length); - assertTrue(Arrays.equals(expected, actual)); + assertArrayEquals(expected, actual); ObjRecord obj = comment.getObjRecord(); ObjRecord objShape = commentShape.getObjRecord(); - /**shapeId = 1025 % 1024**/ - ((CommonObjectDataSubRecord)objShape.getSubRecords().get(0)).setObjectId(1); expected = obj.serialize(); actual = objShape.serialize(); + assertEquals(expected.length, actual.length); + //assertArrayEquals(expected, actual); + TextObjectRecord tor = comment.getTextObjectRecord(); TextObjectRecord torShape = commentShape.getTextObjectRecord(); @@ -88,20 +96,21 @@ public class TestComment extends TestCase { actual = torShape.serialize(); assertEquals(expected.length, actual.length); - assertTrue(Arrays.equals(expected, actual)); + assertArrayEquals(expected, actual); NoteRecord note = comment.getNoteRecord(); NoteRecord noteShape = commentShape.getNoteRecord(); - noteShape.setShapeId(1); expected = note.serialize(); actual = noteShape.serialize(); assertEquals(expected.length, actual.length); - assertTrue(Arrays.equals(expected, actual)); + assertArrayEquals(expected, actual); + + wb.close(); } - public void testAddToExistingFile() { + public void testAddToExistingFile() throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet(); HSSFPatriarch patriarch = sh.createDrawingPatriarch(); @@ -118,8 +127,8 @@ public class TestComment extends TestCase { assertEquals(patriarch.getChildren().size(), 2); - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); + HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wbBack.getSheetAt(0); patriarch = sh.getDrawingPatriarch(); comment = (HSSFComment) patriarch.getChildren().get(1); @@ -132,8 +141,8 @@ public class TestComment extends TestCase { comment.setString(new HSSFRichTextString("comment3")); assertEquals(patriarch.getChildren().size(), 3); - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); + HSSFWorkbook wbBack2 = HSSFTestDataSamples.writeOutAndReadBack(wbBack); + sh = wbBack2.getSheetAt(0); patriarch = sh.getDrawingPatriarch(); comment = (HSSFComment) patriarch.getChildren().get(1); assertEquals(comment.getBackgroundImageId(), 0); @@ -141,6 +150,10 @@ public class TestComment extends TestCase { assertEquals(((HSSFComment) patriarch.getChildren().get(0)).getString().getString(), "comment1"); assertEquals(((HSSFComment) patriarch.getChildren().get(1)).getString().getString(), "comment2"); assertEquals(((HSSFComment) patriarch.getChildren().get(2)).getString().getString(), "comment3"); + + wb.close(); + wbBack.close(); + wbBack2.close(); } public void testSetGetProperties() throws IOException { @@ -164,8 +177,8 @@ public class TestComment extends TestCase { comment.setVisible(false); assertEquals(comment.isVisible(), false); - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); + HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wbBack.getSheetAt(0); patriarch = sh.getDrawingPatriarch(); comment = (HSSFComment) patriarch.getChildren().get(0); @@ -182,8 +195,8 @@ public class TestComment extends TestCase { comment.setRow(42); comment.setVisible(true); - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); + HSSFWorkbook wbBack2 = HSSFTestDataSamples.writeOutAndReadBack(wbBack); + sh = wbBack2.getSheetAt(0); patriarch = sh.getDrawingPatriarch(); comment = (HSSFComment) patriarch.getChildren().get(0); @@ -192,6 +205,10 @@ public class TestComment extends TestCase { assertEquals(comment.getColumn(), 32); assertEquals(comment.getRow(), 42); assertEquals(comment.isVisible(), true); + + wb.close(); + wbBack.close(); + wbBack2.close(); } public void testExistingFileWithComment(){ @@ -206,7 +223,7 @@ public class TestComment extends TestCase { assertEquals(comment.getRow(), 2); } - public void testFindComments(){ + public void testFindComments() throws IOException{ HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet(); HSSFPatriarch patriarch = sh.createDrawingPatriarch(); @@ -221,14 +238,17 @@ public class TestComment extends TestCase { assertNotNull(sh.findCellComment(5, 4)); assertNull(sh.findCellComment(5, 5)); - wb = HSSFTestDataSamples.writeOutAndReadBack(wb); - sh = wb.getSheetAt(0); + HSSFWorkbook wbBack = HSSFTestDataSamples.writeOutAndReadBack(wb); + sh = wbBack.getSheetAt(0); assertNotNull(sh.findCellComment(5, 4)); assertNull(sh.findCellComment(5, 5)); + + wb.close(); + wbBack.close(); } - public void testInitState(){ + public void testInitState() throws IOException{ HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet(); HSSFPatriarch patriarch = sh.createDrawingPatriarch(); @@ -240,11 +260,14 @@ public class TestComment extends TestCase { assertEquals(agg.getTailRecords().size(), 1); HSSFSimpleShape shape = patriarch.createSimpleShape(new HSSFClientAnchor()); + assertNotNull(shape); assertEquals(comment.getOptRecord().getEscherProperties().size(), 10); + + wb.close(); } - public void testShapeId(){ + public void testShapeId() throws IOException{ HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sh = wb.createSheet(); HSSFPatriarch patriarch = sh.createDrawingPatriarch(); @@ -252,20 +275,17 @@ public class TestComment extends TestCase { HSSFComment comment = patriarch.createCellComment(new HSSFClientAnchor()); comment.setShapeId(2024); - /** - * SpRecord.id == shapeId - * ObjRecord.id == shapeId % 1024 - * NoteRecord.id == ObjectRecord.id == shapeId % 1024 - */ assertEquals(comment.getShapeId(), 2024); CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) comment.getObjRecord().getSubRecords().get(0); - assertEquals(cod.getObjectId(), 1000); + assertEquals(2024, cod.getObjectId()); EscherSpRecord spRecord = (EscherSpRecord) comment.getEscherContainer().getChild(0); - assertEquals(spRecord.getShapeId(), 2024); - assertEquals(comment.getShapeId(), 2024); - assertEquals(comment.getNoteRecord().getShapeId(), 1000); + assertEquals(2024, spRecord.getShapeId(), 2024); + assertEquals(2024, comment.getShapeId(), 2024); + assertEquals(2024, comment.getNoteRecord().getShapeId()); + + wb.close(); } public void testAttemptToSave2CommentsWithSameCoordinates(){ diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java index 36a48f46f..7c78fb067 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java @@ -30,10 +30,8 @@ import org.apache.poi.hssf.record.DBCellRecord; import org.apache.poi.hssf.record.FormulaRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.StringRecord; -import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.BaseTestCell; import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.ErrorConstants; import org.apache.poi.ss.usermodel.FormulaError; import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Row; @@ -330,7 +328,7 @@ public final class TestHSSFCell extends BaseTestCell { // string to error code cell.setCellValue("abc"); confirmStringRecord(sheet, true); - cell.setCellErrorValue((byte)ErrorConstants.ERROR_REF); + cell.setCellErrorValue(FormulaError.REF.getCode()); confirmStringRecord(sheet, false); // string to boolean @@ -356,38 +354,6 @@ public final class TestHSSFCell extends BaseTestCell { assertEquals(DBCellRecord.class, dbcr.getClass()); } - /** - * The maximum length of cell contents (text) is 32,767 characters. - * @throws IOException - */ - public void testMaxTextLength() throws IOException{ - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet sheet = wb.createSheet(); - HSSFCell cell = sheet.createRow(0).createCell(0); - - int maxlen = SpreadsheetVersion.EXCEL97.getMaxTextLength(); - assertEquals(32767, maxlen); - - StringBuffer b = new StringBuffer() ; - - // 32767 is okay - for( int i = 0 ; i < maxlen ; i++ ) - { - b.append( "X" ) ; - } - cell.setCellValue(b.toString()); - - b.append("X"); - // 32768 produces an invalid XLS file - try { - cell.setCellValue(b.toString()); - fail("Expected exception"); - } catch (IllegalArgumentException e){ - assertEquals("The maximum length of cell contents (text) is 32,767 characters", e.getMessage()); - } - wb.close(); - } - /** * HSSF prior to version 3.7 had a bug: it could write a NaN but could not read such a file back. */ diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java index 055f21bac..32ca5b598 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFComment.java @@ -17,10 +17,19 @@ package org.apache.poi.hssf.usermodel; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.ss.usermodel.BaseTestCellComment; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.Comment; +import org.apache.poi.ss.usermodel.CreationHelper; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.RichTextString; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; import org.junit.Test; /** @@ -75,4 +84,108 @@ public final class TestHSSFComment extends BaseTestCellComment { comment = cell.getCellComment(); assertEquals("c6", comment.getString().getString()); } + + @Test + public void testBug56380InsertComments() throws Exception { + HSSFWorkbook workbook = new HSSFWorkbook(); + Sheet sheet = workbook.createSheet(); + Drawing drawing = sheet.createDrawingPatriarch(); + int noOfRows = 1025; + String comment = "c"; + + for(int i = 0; i < noOfRows; i++) { + Row row = sheet.createRow(i); + Cell cell = row.createCell(0); + insertComment(drawing, cell, comment + i); + } + + // assert that the comments are created properly before writing + checkComments(sheet, noOfRows, comment); + + /*// store in temp-file + OutputStream fs = new FileOutputStream("/tmp/56380.xls"); + try { + sheet.getWorkbook().write(fs); + } finally { + fs.close(); + }*/ + + // save and recreate the workbook from the saved file + HSSFWorkbook workbookBack = HSSFTestDataSamples.writeOutAndReadBack(workbook); + sheet = workbookBack.getSheetAt(0); + + // assert that the comments are created properly after reading back in + checkComments(sheet, noOfRows, comment); + + workbook.close(); + workbookBack.close(); + } + + @Test + public void testBug56380InsertTooManyComments() throws Exception { + HSSFWorkbook workbook = new HSSFWorkbook(); + try { + Sheet sheet = workbook.createSheet(); + Drawing drawing = sheet.createDrawingPatriarch(); + String comment = "c"; + + for(int rowNum = 0;rowNum < 258;rowNum++) { + sheet.createRow(rowNum); + } + + // should still work, for some reason DrawingManager2.allocateShapeId() skips the first 1024... + for(int count = 1025;count < 65535;count++) { + int rowNum = count / 255; + int cellNum = count % 255; + Cell cell = sheet.getRow(rowNum).createCell(cellNum); + try { + Comment commentObj = insertComment(drawing, cell, comment + cellNum); + + assertEquals(count, ((HSSFComment)commentObj).getNoteRecord().getShapeId()); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("While adding shape number " + count, e); + } + } + + // this should now fail to insert + Row row = sheet.createRow(257); + Cell cell = row.createCell(0); + insertComment(drawing, cell, comment + 0); + } finally { + workbook.close(); + } + } + + private void checkComments(Sheet sheet, int noOfRows, String comment) { + for(int i = 0; i < noOfRows; i++) { + assertNotNull(sheet.getRow(i)); + assertNotNull(sheet.getRow(i).getCell(0)); + assertNotNull("Did not get a Cell Comment for row " + i, sheet.getRow(i).getCell(0).getCellComment()); + assertNotNull(sheet.getRow(i).getCell(0).getCellComment().getString()); + assertEquals(comment + i, sheet.getRow(i).getCell(0).getCellComment().getString().getString()); + } + } + + private Comment insertComment(Drawing drawing, Cell cell, String message) { + CreationHelper factory = cell.getSheet().getWorkbook().getCreationHelper(); + + ClientAnchor anchor = factory.createClientAnchor(); + anchor.setCol1(cell.getColumnIndex()); + anchor.setCol2(cell.getColumnIndex() + 1); + anchor.setRow1(cell.getRowIndex()); + anchor.setRow2(cell.getRowIndex() + 1); + anchor.setDx1(100); + anchor.setDx2(100); + anchor.setDy1(100); + anchor.setDy2(100); + + Comment comment = drawing.createCellComment(anchor); + + RichTextString str = factory.createRichTextString(message); + comment.setString(str); + comment.setAuthor("fanfy"); + cell.setCellComment(comment); + + return comment; + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java index 8cd3cbaac..697f350c7 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFConditionalFormatting.java @@ -22,23 +22,33 @@ import java.io.FileNotFoundException; import java.io.IOException; import org.apache.poi.hssf.HSSFITestDataProvider; +import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.BaseTestConditionalFormatting; +import org.apache.poi.ss.usermodel.Color; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.SheetConditionalFormatting; import org.apache.poi.ss.usermodel.Workbook; /** - * - * @author Dmitriy Kumshayev + * HSSF-specific Conditional Formatting tests */ public final class TestHSSFConditionalFormatting extends BaseTestConditionalFormatting { public TestHSSFConditionalFormatting(){ super(HSSFITestDataProvider.instance); } + protected void assertColour(String hexExpected, Color actual) { + assertNotNull("Colour must be given", actual); + HSSFColor colour = (HSSFColor)actual; + assertEquals(hexExpected, colour.getHexString()); + } - public void testRead(){ + public void testRead() { testRead("WithConditionalFormatting.xls"); } + + public void testReadOffice2007() { + testReadOffice2007("NewStyleConditionalFormattings.xls"); + } public void test53691() throws IOException { SheetConditionalFormatting cf; diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java index f5ea7a1cc..2e34d6f60 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java @@ -17,9 +17,7 @@ package org.apache.poi.hssf.usermodel; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.io.IOException; import java.text.ParseException; @@ -349,6 +347,7 @@ public final class TestHSSFDateUtil { HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("DateFormats.xls"); HSSFSheet sheet = workbook.getSheetAt(0); InternalWorkbook wb = workbook.getWorkbook(); + assertNotNull(wb); HSSFRow row; HSSFCell cell; @@ -481,6 +480,25 @@ public final class TestHSSFDateUtil { assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false)); } + @Test + public void absoluteDayYearTooLow() { + GregorianCalendar calendar = new GregorianCalendar(1899, 0, 1); + try { + HSSFDateUtil.absoluteDay(calendar, false); + fail("Should fail here"); + } catch (IllegalArgumentException e) { + // expected here + } + + try { + calendar = new GregorianCalendar(1903, 0, 1); + HSSFDateUtil.absoluteDay(calendar, true); + fail("Should fail here"); + } catch (IllegalArgumentException e) { + // expected here + } + } + @Test public void convertTime() { diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java index 654db6aa0..dafb481d3 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFRow.java @@ -17,6 +17,8 @@ package org.apache.poi.hssf.usermodel; +import java.io.IOException; + import junit.framework.AssertionFailedError; import org.apache.poi.hssf.HSSFITestDataProvider; @@ -71,7 +73,7 @@ public final class TestHSSFRow extends BaseTestRow { assertEquals(-1, row.getLastCellNum()); } - public void testMoveCell() { + public void testMoveCell() throws IOException { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(); HSSFRow row = sheet.createRow(0); @@ -115,9 +117,11 @@ public final class TestHSSFRow extends BaseTestRow { assertEquals(5, cellB2.getColumnIndex()); assertEquals(2, row.getFirstCellNum()); assertEquals(6, row.getLastCellNum()); + + workbook.close(); } - public void testRowHeight(){ + public void testRowHeight() throws IOException{ HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(); HSSFRow row = sheet.createRow(0); @@ -132,5 +136,7 @@ public final class TestHSSFRow extends BaseTestRow { row.setHeight((short) -1); assertEquals(row.getHeight(), sheet.getDefaultRowHeight()); assertEquals(row.getRowRecord().getBadFontHeight(), false); + + workbook.close(); } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java index 2fabba9de..efe4f01ec 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java @@ -28,6 +28,7 @@ import static org.apache.poi.POITestCase.assertContains; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -1106,4 +1107,36 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook { private void expectName(HSSFWorkbook wb, String name, String expect) { assertEquals(expect, wb.getName(name).getRefersToFormula()); } + + @Test + public void test49423() throws Exception + { + HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("49423.xls"); + + boolean found = false; + int numSheets = workbook.getNumberOfSheets(); + for (int i = 0; i < numSheets; i++) { + HSSFSheet sheet = workbook.getSheetAt(i); + List shapes = sheet.getDrawingPatriarch().getChildren(); + for(HSSFShape shape : shapes){ + HSSFAnchor anchor = shape.getAnchor(); + + if(anchor instanceof HSSFClientAnchor){ + // absolute coordinates + HSSFClientAnchor clientAnchor = (HSSFClientAnchor)anchor; + assertNotNull(clientAnchor); + //System.out.println(clientAnchor.getRow1() + "," + clientAnchor.getRow2()); + found = true; + } else if (anchor instanceof HSSFChildAnchor){ + // shape is grouped and the anchor is expressed in the coordinate system of the group + HSSFChildAnchor childAnchor = (HSSFChildAnchor)anchor; + assertNotNull(childAnchor); + //System.out.println(childAnchor.getDy1() + "," + childAnchor.getDy2()); + found = true; + } + } + } + + assertTrue("Should find some images via Client or Child anchors, but did not find any at all", found); + } } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestUnfixedBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestUnfixedBugs.java index 261554566..d0efcb094 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestUnfixedBugs.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestUnfixedBugs.java @@ -17,8 +17,6 @@ package org.apache.poi.hssf.usermodel; -import static org.junit.Assert.assertEquals; - import java.io.IOException; import junit.framework.AssertionFailedError; diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestDocument.java b/src/testcases/org/apache/poi/poifs/filesystem/TestDocument.java index e216ed9a8..21494b39b 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestDocument.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestDocument.java @@ -28,27 +28,25 @@ import org.apache.poi.poifs.storage.RawDataBlock; import org.apache.poi.poifs.storage.SmallDocumentBlock; /** - * Class to test POIFSDocument functionality - * - * @author Marc Johnson + * Class to test OPOIFSDocument functionality */ public final class TestDocument extends TestCase { /** * Integration test -- really about all we can do */ - public void testPOIFSDocument() throws IOException { + public void testOPOIFSDocument() throws IOException { // verify correct number of blocks get created for document // that is exact multituple of block size - POIFSDocument document; + OPOIFSDocument document; byte[] array = new byte[ 4096 ]; for (int j = 0; j < array.length; j++) { array[ j ] = ( byte ) j; } - document = new POIFSDocument("foo", new SlowInputStream(new ByteArrayInputStream(array))); + document = new OPOIFSDocument("foo", new SlowInputStream(new ByteArrayInputStream(array))); checkDocument(document, array); // verify correct number of blocks get created for document @@ -58,7 +56,7 @@ public final class TestDocument extends TestCase { { array[ j ] = ( byte ) j; } - document = new POIFSDocument("bar", new ByteArrayInputStream(array)); + document = new OPOIFSDocument("bar", new ByteArrayInputStream(array)); checkDocument(document, array); // verify correct number of blocks get created for document @@ -68,7 +66,7 @@ public final class TestDocument extends TestCase { { array[ j ] = ( byte ) j; } - document = new POIFSDocument("_bar", new ByteArrayInputStream(array)); + document = new OPOIFSDocument("_bar", new ByteArrayInputStream(array)); checkDocument(document, array); // verify correct number of blocks get created for document @@ -78,7 +76,7 @@ public final class TestDocument extends TestCase { { array[ j ] = ( byte ) j; } - document = new POIFSDocument("_bar2", + document = new OPOIFSDocument("_bar2", new ByteArrayInputStream(array)); checkDocument(document, array); @@ -88,7 +86,7 @@ public final class TestDocument extends TestCase { { array[ j ] = ( byte ) j; } - document = new POIFSDocument("foobar", + document = new OPOIFSDocument("foobar", new ByteArrayInputStream(array)); checkDocument(document, array); document.setStartBlock(0x12345678); // what a big file!! @@ -135,9 +133,9 @@ public final class TestDocument extends TestCase { } } - private static POIFSDocument makeCopy(POIFSDocument document, byte[] input, byte[] data) + private static OPOIFSDocument makeCopy(OPOIFSDocument document, byte[] input, byte[] data) throws IOException { - POIFSDocument copy = null; + OPOIFSDocument copy = null; if (input.length >= 4096) { @@ -156,12 +154,12 @@ public final class TestDocument extends TestCase { } blocks[ index++ ] = block; } - copy = new POIFSDocument("test" + input.length, blocks, + copy = new OPOIFSDocument("test" + input.length, blocks, input.length); } else { - copy = new POIFSDocument( + copy = new OPOIFSDocument( "test" + input.length, ( SmallDocumentBlock [] ) document.getSmallBlocks(), input.length); @@ -169,7 +167,7 @@ public final class TestDocument extends TestCase { return copy; } - private static void checkDocument(final POIFSDocument document, final byte[] input) + private static void checkDocument(final OPOIFSDocument document, final byte[] input) throws IOException { int big_blocks = 0; int small_blocks = 0; @@ -195,7 +193,7 @@ public final class TestDocument extends TestCase { } private static byte[] checkValues(int big_blocks, int small_blocks, int total_output, - POIFSDocument document, byte[] input) throws IOException { + OPOIFSDocument document, byte[] input) throws IOException { assertEquals(document, document.getDocumentProperty().getDocument()); int increment = ( int ) Math.sqrt(input.length); diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java b/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java index 6ba10f99c..801935865 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java @@ -31,10 +31,7 @@ import org.apache.poi.poifs.storage.RawDataBlock; /** * Class to test DocumentInputStream functionality - * - * @author Marc Johnson */ - public final class TestDocumentInputStream extends TestCase { private DocumentNode _workbook_n; private DocumentNode _workbook_o; @@ -64,8 +61,8 @@ public final class TestDocumentInputStream extends TestCase { { rawBlocks[ j ] = new RawDataBlock(stream); } - POIFSDocument document = new POIFSDocument("Workbook", rawBlocks, - _workbook_size); + OPOIFSDocument document = new OPOIFSDocument("Workbook", rawBlocks, + _workbook_size); _workbook_o = new DocumentNode( document.getDocumentProperty(), @@ -95,7 +92,7 @@ public final class TestDocumentInputStream extends TestCase { * test constructor */ public void testConstructor() throws IOException { - DocumentInputStream ostream = new DocumentInputStream(_workbook_o); + DocumentInputStream ostream = new ODocumentInputStream(_workbook_o); DocumentInputStream nstream = new NDocumentInputStream(_workbook_n); assertEquals(_workbook_size, _workbook_o.getSize()); @@ -103,6 +100,9 @@ public final class TestDocumentInputStream extends TestCase { assertEquals(_workbook_size, ostream.available()); assertEquals(_workbook_size, nstream.available()); + + ostream.close(); + nstream.close(); } /** @@ -514,12 +514,14 @@ public final class TestDocumentInputStream extends TestCase { NPOIFSFileSystem npoifs = new NPOIFSFileSystem(sample); try { - POIFSFileSystem opoifs = new POIFSFileSystem(new FileInputStream(sample)); + OPOIFSFileSystem opoifs = new OPOIFSFileSystem(new FileInputStream(sample)); // Ensure we have what we expect on the root assertEquals(npoifs, npoifs.getRoot().getNFileSystem()); - assertEquals(null, npoifs.getRoot().getFileSystem()); - assertEquals(opoifs, opoifs.getRoot().getFileSystem()); + assertEquals(npoifs, npoifs.getRoot().getFileSystem()); + assertEquals(null, npoifs.getRoot().getOFileSystem()); + assertEquals(null, opoifs.getRoot().getFileSystem()); + assertEquals(opoifs, opoifs.getRoot().getOFileSystem()); assertEquals(null, opoifs.getRoot().getNFileSystem()); // Check inside diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentNode.java b/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentNode.java index 6101494a0..69d167793 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentNode.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestDocumentNode.java @@ -46,7 +46,7 @@ public final class TestDocumentNode extends TestCase { { rawBlocks[ j ] = new RawDataBlock(stream); } - POIFSDocument document = new POIFSDocument("document", rawBlocks, + OPOIFSDocument document = new OPOIFSDocument("document", rawBlocks, 2000); DocumentProperty property2 = document.getDocumentProperty(); DirectoryNode parent = new DirectoryNode(property1, (POIFSFileSystem)null, null); diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestFileSystemBugs.java b/src/testcases/org/apache/poi/poifs/filesystem/TestFileSystemBugs.java new file mode 100644 index 000000000..2f7c67f37 --- /dev/null +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestFileSystemBugs.java @@ -0,0 +1,186 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.filesystem; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.poi.POIDataSamples; + +/** + * Tests bugs across both POIFSFileSystem and NPOIFSFileSystem + */ +public final class TestFileSystemBugs extends TestCase { + protected static POIDataSamples _samples = POIDataSamples.getPOIFSInstance(); + protected static POIDataSamples _ssSamples = POIDataSamples.getSpreadSheetInstance(); + + protected List openedFSs; + protected void tearDown() throws Exception { + if (openedFSs != null && !openedFSs.isEmpty()) { + for (NPOIFSFileSystem fs : openedFSs) { + try { + fs.close(); + } catch (Exception e) { + System.err.println("Error closing FS: " + e); + } + } + } + openedFSs = null; + } + protected DirectoryNode[] openSample(String name, boolean oldFails) throws Exception { + return openSamples(new InputStream[] { + _samples.openResourceAsStream(name), + _samples.openResourceAsStream(name) + }, oldFails); + } + protected DirectoryNode[] openSSSample(String name, boolean oldFails) throws Exception { + return openSamples(new InputStream[] { + _ssSamples.openResourceAsStream(name), + _ssSamples.openResourceAsStream(name) + }, oldFails); + } + protected DirectoryNode[] openSamples(InputStream[] inps, boolean oldFails) throws Exception { + NPOIFSFileSystem nfs = new NPOIFSFileSystem(inps[0]); + if (openedFSs == null) openedFSs = new ArrayList(); + openedFSs.add(nfs); + + OPOIFSFileSystem ofs = null; + try { + ofs = new OPOIFSFileSystem(inps[1]); + if (oldFails) fail("POIFSFileSystem should have failed but didn't"); + } catch (Exception e) { + if (!oldFails) throw e; + } + + if (ofs == null) return new DirectoryNode[] { nfs.getRoot() }; + return new DirectoryNode[] { ofs.getRoot(), nfs.getRoot() }; + } + + /** + * Test that we can open files that come via Lotus notes. + * These have a top level directory without a name.... + */ + public void testNotesOLE2Files() throws Exception { + // Check the contents + for (DirectoryNode root : openSample("Notes.ole2", false)) { + assertEquals(1, root.getEntryCount()); + + Entry entry = root.getEntries().next(); + assertTrue(entry.isDirectoryEntry()); + assertTrue(entry instanceof DirectoryEntry); + + // The directory lacks a name! + DirectoryEntry dir = (DirectoryEntry)entry; + assertEquals("", dir.getName()); + + // Has two children + assertEquals(2, dir.getEntryCount()); + + // Check them + Iterator it = dir.getEntries(); + entry = it.next(); + assertEquals(true, entry.isDocumentEntry()); + assertEquals("\u0001Ole10Native", entry.getName()); + + entry = it.next(); + assertEquals(true, entry.isDocumentEntry()); + assertEquals("\u0001CompObj", entry.getName()); + } + } + + /** + * Ensure that a file with a corrupted property in the + * properties table can still be loaded, and the remaining + * properties used + * Note - only works for NPOIFSFileSystem, POIFSFileSystem + * can't cope with this level of corruption + */ + public void testCorruptedProperties() throws Exception { + for (DirectoryNode root : openSample("unknown_properties.msg", true)) { + assertEquals(42, root.getEntryCount()); + } + } + + /** + * With heavily nested documents, ensure we still re-write the same + */ + public void testHeavilyNestedReWrite() throws Exception { + for (DirectoryNode root : openSSSample("ex42570-20305.xls", false)) { + // Record the structure + Map entries = new HashMap(); + fetchSizes("/", root, entries); + + // Prepare to copy + DirectoryNode dest; + if (root.getNFileSystem() != null) { + dest = (new NPOIFSFileSystem()).getRoot(); + } else { + dest = (new OPOIFSFileSystem()).getRoot(); + } + + // Copy over + EntryUtils.copyNodes(root, dest); + + // Re-load, always as NPOIFS + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + if (root.getNFileSystem() != null) { + root.getNFileSystem().writeFilesystem(baos); + } else { + root.getOFileSystem().writeFilesystem(baos); + } + NPOIFSFileSystem read = new NPOIFSFileSystem( + new ByteArrayInputStream(baos.toByteArray())); + + // Check the structure matches + checkSizes("/", read.getRoot(), entries); + } + } + private void fetchSizes(String path, DirectoryNode dir, Map entries) { + for (Entry entry : dir) { + if (entry instanceof DirectoryNode) { + String ourPath = path + entry.getName() + "/"; + entries.put(ourPath, -1); + fetchSizes(ourPath, (DirectoryNode)entry, entries); + } else { + DocumentNode doc = (DocumentNode)entry; + entries.put(path+entry.getName(), doc.getSize()); + } + } + } + private void checkSizes(String path, DirectoryNode dir, Map entries) { + for (Entry entry : dir) { + if (entry instanceof DirectoryNode) { + String ourPath = path + entry.getName() + "/"; + assertTrue(entries.containsKey(ourPath)); + assertEquals(-1, entries.get(ourPath).intValue()); + checkSizes(ourPath, (DirectoryNode)entry, entries); + } else { + DocumentNode doc = (DocumentNode)entry; + assertEquals(entries.get(path+entry.getName()).intValue(), doc.getSize()); + } + } + } +} diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java index b5793a266..ed598ed6c 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java @@ -20,6 +20,7 @@ package org.apache.poi.poifs.filesystem; import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; @@ -935,27 +936,27 @@ public final class TestNPOIFSFileSystem { DocumentEntry miniDoc; DocumentEntry normDoc; - // Initially has a BAT but not SBAT - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); + // Initially has Properties + BAT but not SBAT + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(2)); // Check that the SBAT is empty assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); - // Check that no properties table has been written yet - assertEquals(POIFSConstants.END_OF_CHAIN, fs._get_property_table().getStartBlock()); + // Check that properties table was given block 0 + assertEquals(0, fs._get_property_table().getStartBlock()); // Write and read it fs = writeOutAndReadBack(fs); - // Property table entries have been added to the blocks - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(3)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); - assertEquals(2, fs._get_property_table().getStartBlock()); + // No change, SBAT remains empty + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(2)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(3)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); + assertEquals(0, fs._get_property_table().getStartBlock()); // Put everything within a new directory @@ -967,19 +968,19 @@ public final class TestNPOIFSFileSystem { main4096[4095] = -11; testDir.createDocument("Normal4096", new ByteArrayInputStream(main4096)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); + assertEquals(3, fs.getNextBlock(2)); assertEquals(4, fs.getNextBlock(3)); assertEquals(5, fs.getNextBlock(4)); assertEquals(6, fs.getNextBlock(5)); assertEquals(7, fs.getNextBlock(6)); assertEquals(8, fs.getNextBlock(7)); assertEquals(9, fs.getNextBlock(8)); - assertEquals(10, fs.getNextBlock(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(10)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(9)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(10)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(11)); - + // SBAT still unused assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); @@ -989,18 +990,18 @@ public final class TestNPOIFSFileSystem { main5124[5123] = -33; testDir.createDocument("Normal5124", new ByteArrayInputStream(main5124)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); + assertEquals(3, fs.getNextBlock(2)); assertEquals(4, fs.getNextBlock(3)); assertEquals(5, fs.getNextBlock(4)); assertEquals(6, fs.getNextBlock(5)); assertEquals(7, fs.getNextBlock(6)); assertEquals(8, fs.getNextBlock(7)); assertEquals(9, fs.getNextBlock(8)); - assertEquals(10, fs.getNextBlock(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(10)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(9)); + assertEquals(11, fs.getNextBlock(10)); assertEquals(12, fs.getNextBlock(11)); assertEquals(13, fs.getNextBlock(12)); assertEquals(14, fs.getNextBlock(13)); @@ -1010,8 +1011,8 @@ public final class TestNPOIFSFileSystem { assertEquals(18, fs.getNextBlock(17)); assertEquals(19, fs.getNextBlock(18)); assertEquals(20, fs.getNextBlock(19)); - assertEquals(21, fs.getNextBlock(20)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(21)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(20)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(21)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(22)); assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); @@ -1022,18 +1023,18 @@ public final class TestNPOIFSFileSystem { testDir.createDocument("Mini", new ByteArrayInputStream(mini)); // Mini stream will get one block for fat + one block for data - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); + assertEquals(3, fs.getNextBlock(2)); assertEquals(4, fs.getNextBlock(3)); assertEquals(5, fs.getNextBlock(4)); assertEquals(6, fs.getNextBlock(5)); assertEquals(7, fs.getNextBlock(6)); assertEquals(8, fs.getNextBlock(7)); assertEquals(9, fs.getNextBlock(8)); - assertEquals(10, fs.getNextBlock(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(10)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(9)); + assertEquals(11, fs.getNextBlock(10)); assertEquals(12, fs.getNextBlock(11)); assertEquals(13, fs.getNextBlock(12)); assertEquals(14, fs.getNextBlock(13)); @@ -1043,15 +1044,14 @@ public final class TestNPOIFSFileSystem { assertEquals(18, fs.getNextBlock(17)); assertEquals(19, fs.getNextBlock(18)); assertEquals(20, fs.getNextBlock(19)); - assertEquals(21, fs.getNextBlock(20)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(20)); assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(21)); assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(22)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(23)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(24)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(23)); // Check the mini stream location was set - // (22 is mini fat, 23 is first mini stream block) - assertEquals(23, fs.getRoot().getProperty().getStartBlock()); + // (21 is mini fat, 22 is first mini stream block) + assertEquals(22, fs.getRoot().getProperty().getStartBlock()); // Write and read back @@ -1060,28 +1060,28 @@ public final class TestNPOIFSFileSystem { // Check the header has the right points in it assertEquals(1, header.getBATCount()); - assertEquals(0, header.getBATArray()[0]); - assertEquals(2, header.getPropertyStart()); + assertEquals(1, header.getBATArray()[0]); + assertEquals(0, header.getPropertyStart()); assertEquals(1, header.getSBATCount()); - assertEquals(22, header.getSBATStart()); - assertEquals(23, fs._get_property_table().getRoot().getStartBlock()); + assertEquals(21, header.getSBATStart()); + assertEquals(22, fs._get_property_table().getRoot().getStartBlock()); // Block use should be almost the same, except the properties // stream will have grown out to cover 2 blocks // Check the block use is all unchanged - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); - assertEquals(24, fs.getNextBlock(2)); // Properties now extends over 2 blocks + assertEquals(23, fs.getNextBlock(0)); // Properties now extends over 2 blocks + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); + assertEquals(3, fs.getNextBlock(2)); assertEquals(4, fs.getNextBlock(3)); assertEquals(5, fs.getNextBlock(4)); assertEquals(6, fs.getNextBlock(5)); assertEquals(7, fs.getNextBlock(6)); assertEquals(8, fs.getNextBlock(7)); assertEquals(9, fs.getNextBlock(8)); - assertEquals(10, fs.getNextBlock(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(10)); // End of normal4096 + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(9)); // End of normal4096 + assertEquals(11, fs.getNextBlock(10)); assertEquals(12, fs.getNextBlock(11)); assertEquals(13, fs.getNextBlock(12)); assertEquals(14, fs.getNextBlock(13)); @@ -1091,13 +1091,12 @@ public final class TestNPOIFSFileSystem { assertEquals(18, fs.getNextBlock(17)); assertEquals(19, fs.getNextBlock(18)); assertEquals(20, fs.getNextBlock(19)); - assertEquals(21, fs.getNextBlock(20)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(21)); // End of normal5124 + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(20)); // End of normal5124 - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(22)); // Mini Stream FAT - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(23)); // Mini Stream data - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(24)); // Properties #2 - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(25)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(21)); // Mini Stream FAT + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(22)); // Mini Stream data + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(23)); // Properties #2 + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(24)); // Check some data @@ -1123,19 +1122,19 @@ public final class TestNPOIFSFileSystem { // Check - will have un-used sectors now fs = writeOutAndReadBack(fs); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); // Props back in 1 block + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); // Props back in 1 block + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); + assertEquals(3, fs.getNextBlock(2)); assertEquals(4, fs.getNextBlock(3)); assertEquals(5, fs.getNextBlock(4)); assertEquals(6, fs.getNextBlock(5)); assertEquals(7, fs.getNextBlock(6)); assertEquals(8, fs.getNextBlock(7)); assertEquals(9, fs.getNextBlock(8)); - assertEquals(10, fs.getNextBlock(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(10)); // End of normal4096 + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(9)); // End of normal4096 + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(10)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(11)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(12)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(13)); @@ -1146,11 +1145,11 @@ public final class TestNPOIFSFileSystem { assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(18)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(19)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(20)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(21)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(22)); // Mini Stream FAT - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(23)); // Mini Stream data - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(24)); // Properties gone + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(21)); // Mini Stream FAT + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(22)); // Mini Stream data + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(23)); // Properties gone + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(24)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(25)); // All done @@ -1164,20 +1163,20 @@ public final class TestNPOIFSFileSystem { DocumentEntry normDoc; HeaderBlock hdr; - // Initially has BAT + Properties but nothing else - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); + // Initially has Properties + BAT but nothing else + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(2)); hdr = writeOutAndReadHeader(fs); // No mini stream, and no xbats // Will have fat then properties stream assertEquals(1, hdr.getBATCount()); - assertEquals(0, hdr.getBATArray()[0]); - assertEquals(2, hdr.getPropertyStart()); + assertEquals(1, hdr.getBATArray()[0]); + assertEquals(0, hdr.getPropertyStart()); assertEquals(POIFSConstants.END_OF_CHAIN, hdr.getSBATStart()); assertEquals(POIFSConstants.END_OF_CHAIN, hdr.getXBATIndex()); - assertEquals(POIFSConstants.SMALLER_BIG_BLOCK_SIZE*4, fs.size()); + assertEquals(POIFSConstants.SMALLER_BIG_BLOCK_SIZE*3, fs.size()); // Get a clean filesystem to start with @@ -1200,8 +1199,8 @@ public final class TestNPOIFSFileSystem { // Check the mini stream was added, then the main stream - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); // Mini Fat assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); // Mini Stream assertEquals(5, fs.getNextBlock(4)); // Main Stream @@ -1231,15 +1230,15 @@ public final class TestNPOIFSFileSystem { // Check the header details - will have the sbat near the start, // then the properties at the end assertEquals(1, hdr.getBATCount()); - assertEquals(0, hdr.getBATArray()[0]); + assertEquals(1, hdr.getBATArray()[0]); assertEquals(2, hdr.getSBATStart()); - assertEquals(12, hdr.getPropertyStart()); + assertEquals(0, hdr.getPropertyStart()); assertEquals(POIFSConstants.END_OF_CHAIN, hdr.getXBATIndex()); // Check the block allocation is unchanged, other than // the properties stream going in at the end - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); + assertEquals(12, fs.getNextBlock(0)); // Properties + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); assertEquals(5, fs.getNextBlock(4)); @@ -1250,10 +1249,9 @@ public final class TestNPOIFSFileSystem { assertEquals(10, fs.getNextBlock(9)); assertEquals(11, fs.getNextBlock(10)); assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(11)); - assertEquals(13, fs.getNextBlock(12)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(13)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(14)); - assertEquals(POIFSConstants.SMALLER_BIG_BLOCK_SIZE*15, fs.size()); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(12)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(13)); + assertEquals(POIFSConstants.SMALLER_BIG_BLOCK_SIZE*14, fs.size()); // Check the data @@ -1304,6 +1302,138 @@ public final class TestNPOIFSFileSystem { normDoc = (DocumentEntry)testDir.getEntry("Normal4106"); assertContentsMatches(main4106, normDoc); + + // All done + fs.close(); + } + + @Test + public void readZeroLengthEntries() throws Exception { + NPOIFSFileSystem fs = new NPOIFSFileSystem(_inst.getFile("only-zero-byte-streams.ole2")); + DirectoryNode testDir = fs.getRoot(); + assertEquals(3, testDir.getEntryCount()); + DocumentEntry entry; + + entry = (DocumentEntry)testDir.getEntry("test-zero-1"); + assertNotNull(entry); + assertEquals(0, entry.getSize()); + + entry = (DocumentEntry)testDir.getEntry("test-zero-2"); + assertNotNull(entry); + assertEquals(0, entry.getSize()); + + entry = (DocumentEntry)testDir.getEntry("test-zero-3"); + assertNotNull(entry); + assertEquals(0, entry.getSize()); + + // Check properties, all have zero length, no blocks + NPropertyTable props = fs._get_property_table(); + assertEquals(POIFSConstants.END_OF_CHAIN, props.getRoot().getStartBlock()); + for (Property prop : props.getRoot()) { + assertEquals("test-zero-", prop.getName().substring(0, 10)); + assertEquals(POIFSConstants.END_OF_CHAIN, prop.getStartBlock()); + } + + // All done + fs.close(); + } + + @Test + public void writeZeroLengthEntries() throws Exception { + NPOIFSFileSystem fs = new NPOIFSFileSystem(); + DirectoryNode testDir = fs.getRoot(); + DocumentEntry miniDoc; + DocumentEntry normDoc; + DocumentEntry emptyDoc; + + // Add mini and normal sized entries to start + byte[] mini2 = new byte[] { -42, 0, -1, -2, -3, -4, -42 }; + testDir.createDocument("Mini2", new ByteArrayInputStream(mini2)); + + // Add to the main stream + byte[] main4106 = new byte[4106]; + main4106[0] = 41; + main4106[4105] = 42; + testDir.createDocument("Normal4106", new ByteArrayInputStream(main4106)); + + // Now add some empty ones + byte[] empty = new byte[0]; + testDir.createDocument("empty-1", new ByteArrayInputStream(empty)); + testDir.createDocument("empty-2", new ByteArrayInputStream(empty)); + testDir.createDocument("empty-3", new ByteArrayInputStream(empty)); + + // Check + miniDoc = (DocumentEntry)testDir.getEntry("Mini2"); + assertContentsMatches(mini2, miniDoc); + + normDoc = (DocumentEntry)testDir.getEntry("Normal4106"); + assertContentsMatches(main4106, normDoc); + + emptyDoc = (DocumentEntry)testDir.getEntry("empty-1"); + assertContentsMatches(empty, emptyDoc); + + emptyDoc = (DocumentEntry)testDir.getEntry("empty-2"); + assertContentsMatches(empty, emptyDoc); + + emptyDoc = (DocumentEntry)testDir.getEntry("empty-3"); + assertContentsMatches(empty, emptyDoc); + + // Look at the properties entry, and check the empty ones + // have zero size and no start block + NPropertyTable props = fs._get_property_table(); + Iterator propsIt = props.getRoot().getChildren(); + + Property prop = propsIt.next(); + assertEquals("Mini2", prop.getName()); + assertEquals(0, prop.getStartBlock()); + assertEquals(7, prop.getSize()); + + prop = propsIt.next(); + assertEquals("Normal4106", prop.getName()); + assertEquals(4, prop.getStartBlock()); // BAT, Props, SBAT, MIni + assertEquals(4106, prop.getSize()); + + prop = propsIt.next(); + assertEquals("empty-1", prop.getName()); + assertEquals(POIFSConstants.END_OF_CHAIN, prop.getStartBlock()); + assertEquals(0, prop.getSize()); + + prop = propsIt.next(); + assertEquals("empty-2", prop.getName()); + assertEquals(POIFSConstants.END_OF_CHAIN, prop.getStartBlock()); + assertEquals(0, prop.getSize()); + + prop = propsIt.next(); + assertEquals("empty-3", prop.getName()); + assertEquals(POIFSConstants.END_OF_CHAIN, prop.getStartBlock()); + assertEquals(0, prop.getSize()); + + + // Save and re-check + fs = writeOutAndReadBack(fs); + testDir = fs.getRoot(); + + miniDoc = (DocumentEntry)testDir.getEntry("Mini2"); + assertContentsMatches(mini2, miniDoc); + + normDoc = (DocumentEntry)testDir.getEntry("Normal4106"); + assertContentsMatches(main4106, normDoc); + + emptyDoc = (DocumentEntry)testDir.getEntry("empty-1"); + assertContentsMatches(empty, emptyDoc); + + emptyDoc = (DocumentEntry)testDir.getEntry("empty-2"); + assertContentsMatches(empty, emptyDoc); + + emptyDoc = (DocumentEntry)testDir.getEntry("empty-3"); + assertContentsMatches(empty, emptyDoc); + + // Check that a mini-stream was assigned, with one block used + assertEquals(3, testDir.getProperty().getStartBlock()); + assertEquals(64, testDir.getProperty().getSize()); + + // All done + fs.close(); } /** diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java index c875c5299..4f102084d 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java @@ -17,18 +17,19 @@ package org.apache.poi.poifs.filesystem; +import java.io.ByteArrayInputStream; import java.nio.ByteBuffer; import java.util.Iterator; -import junit.framework.TestCase; - import org.apache.poi.POIDataSamples; +import org.apache.poi.POITestCase; import org.apache.poi.poifs.common.POIFSConstants; +import org.apache.poi.util.IOUtils; /** * Tests for the Mini Store in the NIO POIFS */ -public final class TestNPOIFSMiniStore extends TestCase { +public final class TestNPOIFSMiniStore extends POITestCase { private static final POIDataSamples _inst = POIDataSamples.getPOIFSInstance(); /** @@ -332,4 +333,130 @@ public final class TestNPOIFSMiniStore extends TestCase { fs.close(); } + + public void testCreateMiniStoreFirst() throws Exception { + NPOIFSFileSystem fs = new NPOIFSFileSystem(); + NPOIFSMiniStore ministore = fs.getMiniStore(); + DocumentInputStream dis; + DocumentEntry entry; + + // Initially has Properties + BAT but nothing else + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(2)); + // Ministore has no blocks, so can't iterate until used + try { + ministore.getNextBlock(0); + } catch (IndexOutOfBoundsException e) {} + + // Write a very small new document, will populate the ministore for us + byte[] data = new byte[8]; + for (int i=0; i it = stream.getBlockIterator(); @@ -927,11 +927,11 @@ public final class TestNPOIFSStream extends TestCase { public void testWriteThenReplace() throws Exception { NPOIFSFileSystem fs = new NPOIFSFileSystem(); - // Starts empty + // Starts empty, other that Properties and BAT BATBlock bat = fs.getBATBlockAndIndex(0).getBlock(); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(1)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(2)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); + assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(2)); // Write something that uses a main stream byte[] main4106 = new byte[4106]; @@ -941,8 +941,8 @@ public final class TestNPOIFSStream extends TestCase { "Normal", new ByteArrayInputStream(main4106)); // Should have used 9 blocks - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); assertEquals(3, bat.getValueAt(2)); assertEquals(4, bat.getValueAt(3)); assertEquals(5, bat.getValueAt(4)); @@ -969,8 +969,8 @@ public final class TestNPOIFSStream extends TestCase { nout.close(); // Will have dropped to 8 - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); assertEquals(3, bat.getValueAt(2)); assertEquals(4, bat.getValueAt(3)); assertEquals(5, bat.getValueAt(4)); @@ -991,9 +991,9 @@ public final class TestNPOIFSStream extends TestCase { fs = writeOutAndReadBack(fs); bat = fs.getBATBlockAndIndex(0).getBlock(); - // Will have properties, but otherwise the same - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(1)); + // No change after write + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); // Properties + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); assertEquals(3, bat.getValueAt(2)); assertEquals(4, bat.getValueAt(3)); assertEquals(5, bat.getValueAt(4)); @@ -1002,7 +1002,7 @@ public final class TestNPOIFSStream extends TestCase { assertEquals(8, bat.getValueAt(7)); assertEquals(9, bat.getValueAt(8)); assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(9)); // End of Normal - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); // Props + assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(10)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); @@ -1010,14 +1010,14 @@ public final class TestNPOIFSStream extends TestCase { assertEquals(4096, ((DocumentNode)normal).getProperty().getSize()); - // Make longer, take 1 block after the properties too + // Make longer, take 1 block at the end normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); nout = new NDocumentOutputStream(normal); nout.write(main4106); nout.close(); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); assertEquals(3, bat.getValueAt(2)); assertEquals(4, bat.getValueAt(3)); assertEquals(5, bat.getValueAt(4)); @@ -1025,9 +1025,9 @@ public final class TestNPOIFSStream extends TestCase { assertEquals(7, bat.getValueAt(6)); assertEquals(8, bat.getValueAt(7)); assertEquals(9, bat.getValueAt(8)); - assertEquals(11, bat.getValueAt(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); // Props - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(11)); // Normal + assertEquals(10, bat.getValueAt(9)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); // Normal + assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); @@ -1042,8 +1042,8 @@ public final class TestNPOIFSStream extends TestCase { nout.write(mini); nout.close(); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(1)); assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(2)); // SBAT assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(3)); // Mini Stream assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(4)); @@ -1052,7 +1052,7 @@ public final class TestNPOIFSStream extends TestCase { assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(7)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(8)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); // Props + assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(10)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); @@ -1067,8 +1067,8 @@ public final class TestNPOIFSStream extends TestCase { nout.close(); // Will keep the mini stream, now empty - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(1)); assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(2)); // SBAT assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(3)); // Mini Stream assertEquals(5, bat.getValueAt(4)); @@ -1076,10 +1076,10 @@ public final class TestNPOIFSStream extends TestCase { assertEquals(7, bat.getValueAt(6)); assertEquals(8, bat.getValueAt(7)); assertEquals(9, bat.getValueAt(8)); - assertEquals(11, bat.getValueAt(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); // Props - assertEquals(12, bat.getValueAt(11)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(12)); + assertEquals(10, bat.getValueAt(9)); + assertEquals(11, bat.getValueAt(10)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(11)); + assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(13)); normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); @@ -1091,8 +1091,8 @@ public final class TestNPOIFSStream extends TestCase { fs = writeOutAndReadBack(fs); bat = fs.getBATBlockAndIndex(0).getBlock(); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(0)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(1)); assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(2)); // SBAT assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(3)); // Mini Stream assertEquals(5, bat.getValueAt(4)); @@ -1100,10 +1100,10 @@ public final class TestNPOIFSStream extends TestCase { assertEquals(7, bat.getValueAt(6)); assertEquals(8, bat.getValueAt(7)); assertEquals(9, bat.getValueAt(8)); - assertEquals(11, bat.getValueAt(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); // Props - assertEquals(12, bat.getValueAt(11)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(12)); + assertEquals(10, bat.getValueAt(9)); + assertEquals(11, bat.getValueAt(10)); + assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(11)); + assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(13)); normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java b/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java index de5824efe..2655b4414 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java @@ -22,7 +22,6 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; -import java.util.Iterator; import junit.framework.TestCase; @@ -36,13 +35,10 @@ import org.apache.poi.poifs.storage.HeaderBlock; import org.apache.poi.poifs.storage.RawDataBlockList; /** - * Tests for POIFSFileSystem - * - * @author Josh Micich + * Tests for the older OPOIFS-based POIFSFileSystem */ public final class TestPOIFSFileSystem extends TestCase { private POIDataSamples _samples = POIDataSamples.getPOIFSInstance(); - /** * Mock exception used to ensure correct error handling @@ -108,7 +104,7 @@ public final class TestPOIFSFileSystem extends TestCase { // Normal case - read until EOF and close testIS = new TestIS(openSampleStream("13224.xls"), -1); try { - new POIFSFileSystem(testIS); + new OPOIFSFileSystem(testIS); } catch (IOException e) { throw new RuntimeException(e); } @@ -117,7 +113,7 @@ public final class TestPOIFSFileSystem extends TestCase { // intended to crash after reading 10000 bytes testIS = new TestIS(openSampleStream("13224.xls"), 10000); try { - new POIFSFileSystem(testIS); + new OPOIFSFileSystem(testIS); fail("ex should have been thrown"); } catch (IOException e) { throw new RuntimeException(e); @@ -145,7 +141,7 @@ public final class TestPOIFSFileSystem extends TestCase { for(int i=0; i 3); @@ -272,7 +268,7 @@ public final class TestPOIFSFileSystem extends TestCase { checkAllDirectoryContents(fs.getRoot()); // Finally, check we can do a similar 512byte one too - fs = new POIFSFileSystem( + fs = new OPOIFSFileSystem( _samples.openResourceAsStream("BlockSize512.zvi")); assertTrue(fs.getRoot().getEntryCount() > 3); checkAllDirectoryContents(fs.getRoot()); @@ -297,43 +293,6 @@ public final class TestPOIFSFileSystem extends TestCase { } } } - - /** - * Test that we can open files that come via Lotus notes. - * These have a top level directory without a name.... - */ - public void testNotesOLE2Files() throws Exception { - POIDataSamples _samples = POIDataSamples.getPOIFSInstance(); - - // Open the file up - POIFSFileSystem fs = new POIFSFileSystem( - _samples.openResourceAsStream("Notes.ole2") - ); - - // Check the contents - assertEquals(1, fs.getRoot().getEntryCount()); - - Entry entry = fs.getRoot().getEntries().next(); - assertTrue(entry.isDirectoryEntry()); - assertTrue(entry instanceof DirectoryEntry); - - // The directory lacks a name! - DirectoryEntry dir = (DirectoryEntry)entry; - assertEquals("", dir.getName()); - - // Has two children - assertEquals(2, dir.getEntryCount()); - - // Check them - Iterator it = dir.getEntries(); - entry = it.next(); - assertEquals(true, entry.isDocumentEntry()); - assertEquals("\u0001Ole10Native", entry.getName()); - - entry = it.next(); - assertEquals(true, entry.isDocumentEntry()); - assertEquals("\u0001CompObj", entry.getName()); - } private static InputStream openSampleStream(String sampleFileName) { return HSSFTestDataSamples.openSampleFileStream(sampleFileName); diff --git a/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java b/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java index 3fc77b839..11c7070e9 100644 --- a/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java +++ b/src/testcases/org/apache/poi/poifs/storage/TestBATBlock.java @@ -26,6 +26,7 @@ import java.util.List; import junit.framework.TestCase; +import org.apache.poi.poifs.common.POIFSBigBlockSize; import org.apache.poi.poifs.common.POIFSConstants; /** @@ -283,6 +284,59 @@ public final class TestBATBlock extends TestCase { ); } + public void testUsedSectors() throws Exception { + POIFSBigBlockSize b512 = POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS; + POIFSBigBlockSize b4096 = POIFSConstants.LARGER_BIG_BLOCK_SIZE_DETAILS; + + // Try first with 512 block sizes, which can hold 128 entries + BATBlock block512 = BATBlock.createEmptyBATBlock(b512, false); + assertEquals(true, block512.hasFreeSectors()); + assertEquals(0, block512.getUsedSectors(false)); + + // Allocate a few + block512.setValueAt(0, 42); + block512.setValueAt(10, 42); + block512.setValueAt(20, 42); + assertEquals(true, block512.hasFreeSectors()); + assertEquals(3, block512.getUsedSectors(false)); + + // Allocate all + for (int i=0; i blocks = new ArrayList(); diff --git a/src/testcases/org/apache/poi/poifs/storage/TestSmallBlockTableWriter.java b/src/testcases/org/apache/poi/poifs/storage/TestSmallBlockTableWriter.java index f10576a4a..9bb4f6a16 100644 --- a/src/testcases/org/apache/poi/poifs/storage/TestSmallBlockTableWriter.java +++ b/src/testcases/org/apache/poi/poifs/storage/TestSmallBlockTableWriter.java @@ -25,7 +25,7 @@ import java.util.List; import junit.framework.TestCase; import org.apache.poi.poifs.common.POIFSConstants; -import org.apache.poi.poifs.filesystem.POIFSDocument; +import org.apache.poi.poifs.filesystem.OPOIFSDocument; import org.apache.poi.poifs.property.PropertyTable; import org.apache.poi.poifs.property.RootProperty; @@ -37,43 +37,43 @@ import org.apache.poi.poifs.property.RootProperty; public final class TestSmallBlockTableWriter extends TestCase { public void testWritingConstructor() throws IOException { - List documents = new ArrayList(); + List documents = new ArrayList(); documents.add( - new POIFSDocument( + new OPOIFSDocument( "doc340", new ByteArrayInputStream(new byte[ 340 ]))); documents.add( - new POIFSDocument( + new OPOIFSDocument( "doc5000", new ByteArrayInputStream(new byte[ 5000 ]))); documents - .add(new POIFSDocument("doc0", + .add(new OPOIFSDocument("doc0", new ByteArrayInputStream(new byte[ 0 ]))); documents - .add(new POIFSDocument("doc1", + .add(new OPOIFSDocument("doc1", new ByteArrayInputStream(new byte[ 1 ]))); documents - .add(new POIFSDocument("doc2", + .add(new OPOIFSDocument("doc2", new ByteArrayInputStream(new byte[ 2 ]))); documents - .add(new POIFSDocument("doc3", + .add(new OPOIFSDocument("doc3", new ByteArrayInputStream(new byte[ 3 ]))); documents - .add(new POIFSDocument("doc4", + .add(new OPOIFSDocument("doc4", new ByteArrayInputStream(new byte[ 4 ]))); documents - .add(new POIFSDocument("doc5", + .add(new OPOIFSDocument("doc5", new ByteArrayInputStream(new byte[ 5 ]))); documents - .add(new POIFSDocument("doc6", + .add(new OPOIFSDocument("doc6", new ByteArrayInputStream(new byte[ 6 ]))); documents - .add(new POIFSDocument("doc7", + .add(new OPOIFSDocument("doc7", new ByteArrayInputStream(new byte[ 7 ]))); documents - .add(new POIFSDocument("doc8", + .add(new OPOIFSDocument("doc8", new ByteArrayInputStream(new byte[ 8 ]))); documents - .add(new POIFSDocument("doc9", + .add(new OPOIFSDocument("doc9", new ByteArrayInputStream(new byte[ 9 ]))); HeaderBlock header = new HeaderBlock(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS); diff --git a/src/testcases/org/apache/poi/poifs/storage/TestSmallDocumentBlock.java b/src/testcases/org/apache/poi/poifs/storage/TestSmallDocumentBlock.java index b061483c6..31c4546a4 100644 --- a/src/testcases/org/apache/poi/poifs/storage/TestSmallDocumentBlock.java +++ b/src/testcases/org/apache/poi/poifs/storage/TestSmallDocumentBlock.java @@ -21,13 +21,12 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import org.apache.poi.poifs.common.POIFSConstants; - import junit.framework.TestCase; +import org.apache.poi.poifs.common.POIFSConstants; + /** * Class to test SmallDocumentBlock functionality * @@ -53,7 +52,7 @@ public final class TestSmallDocumentBlock extends TestCase { throws IOException { ByteArrayInputStream stream = new ByteArrayInputStream(_testdata); - List documents = new ArrayList(); + List documents = new ArrayList(); while (true) { @@ -66,9 +65,8 @@ public final class TestSmallDocumentBlock extends TestCase { } } SmallDocumentBlock[] results = - SmallDocumentBlock - .convert(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,( BlockWritable [] ) documents - .toArray(new DocumentBlock[ 0 ]), _testdata_size); + SmallDocumentBlock.convert(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, + documents.toArray(new DocumentBlock[ 0 ]), _testdata_size); assertEquals("checking correct result size: ", (_testdata_size + 63) / 64, results.length); @@ -142,20 +140,20 @@ public final class TestSmallDocumentBlock extends TestCase { { for (int j = 0; j <= 8; j++) { - List foo = new ArrayList(); + List blocks = new ArrayList(); for (int k = 0; k < j; k++) { - foo.add(new Object()); + blocks.add(new SmallDocumentBlock(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS)); } - int result = SmallDocumentBlock.fill(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,foo); + int result = SmallDocumentBlock.fill(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, blocks); assertEquals("correct big block count: ", (j + 7) / 8, result); assertEquals("correct small block count: ", 8 * result, - foo.size()); - for (int m = j; m < foo.size(); m++) + blocks.size()); + for (int m = j; m < blocks.size(); m++) { - BlockWritable block = ( BlockWritable ) foo.get(m); + BlockWritable block = blocks.get(m); ByteArrayOutputStream stream = new ByteArrayOutputStream(); block.writeBlocks(stream); @@ -208,13 +206,12 @@ public final class TestSmallDocumentBlock extends TestCase { { new RawDataBlock(new ByteArrayInputStream(data)) }; - List output = SmallDocumentBlock.extract(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,blocks); - Iterator iter = output.iterator(); + List output = SmallDocumentBlock.extract(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS,blocks); offset = 0; - while (iter.hasNext()) + for (SmallDocumentBlock block : output) { - byte[] out_data = (( SmallDocumentBlock ) iter.next()).getData(); + byte[] out_data = block.getData(); assertEquals("testing block at offset " + offset, 64, out_data.length); diff --git a/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java b/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java index 13581c8a4..617f7b052 100644 --- a/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java +++ b/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java @@ -516,6 +516,7 @@ public final class ExcelFileFormatDocFunctionExtractor { ps.println("#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )"); ps.println(""); try { + // can't use ZipHelper here, because its in a different module ZipFile zf = new ZipFile(effDocFile); InputStream is = zf.getInputStream(zf.getEntry("content.xml")); extractFunctionData(new FunctionDataCollector(ps), is); diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunction.java b/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunction.java new file mode 100644 index 000000000..628df033d --- /dev/null +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestLogicalFunction.java @@ -0,0 +1,105 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.ss.formula.functions; + +import java.io.IOException; + +import junit.framework.TestCase; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellValue; +import org.apache.poi.ss.usermodel.FormulaEvaluator; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellReference; + +/** + * LogicalFunction unit tests. + */ +public class TestLogicalFunction extends TestCase { + + private FormulaEvaluator evaluator; + private Row row3; + private Cell cell1; + private Cell cell2; + + @Override + public void setUp() throws IOException { + Workbook wb = new HSSFWorkbook(); + try { + buildWorkbook(wb); + } finally { + wb.close(); + } + } + + private void buildWorkbook(Workbook wb) { + Sheet sh = wb.createSheet(); + Row row1 = sh.createRow(0); + Row row2 = sh.createRow(1); + row3 = sh.createRow(2); + + row1.createCell(0, Cell.CELL_TYPE_NUMERIC); + row1.createCell(1, Cell.CELL_TYPE_NUMERIC); + + row2.createCell(0, Cell.CELL_TYPE_NUMERIC); + row2.createCell(1, Cell.CELL_TYPE_NUMERIC); + + row3.createCell(0); + row3.createCell(1); + + CellReference a1 = new CellReference("A1"); + CellReference a2 = new CellReference("A2"); + CellReference b1 = new CellReference("B1"); + CellReference b2 = new CellReference("B2"); + + sh.getRow(a1.getRow()).getCell(a1.getCol()).setCellValue(35); + sh.getRow(a2.getRow()).getCell(a2.getCol()).setCellValue(0); + sh.getRow(b1.getRow()).getCell(b1.getCol()).setCellFormula("A1/A2"); + sh.getRow(b2.getRow()).getCell(b2.getCol()).setCellFormula("NA()"); + + evaluator = wb.getCreationHelper().createFormulaEvaluator(); + } + + public void testIsErr() { + cell1 = row3.createCell(0); + cell1.setCellFormula("ISERR(B1)"); // produces #DIV/0! + cell2 = row3.createCell(1); + cell2.setCellFormula("ISERR(B2)"); // produces #N/A + + CellValue cell1Value = evaluator.evaluate(cell1); + CellValue cell2Value = evaluator.evaluate(cell2); + + assertEquals(true, cell1Value.getBooleanValue()); + assertEquals(false, cell2Value.getBooleanValue()); + } + + public void testIsError() { + cell1 = row3.createCell(0); + cell1.setCellFormula("ISERROR(B1)"); // produces #DIV/0! + cell2 = row3.createCell(1); + cell2.setCellFormula("ISERROR(B2)"); // produces #N/A + + CellValue cell1Value = evaluator.evaluate(cell1); + CellValue cell2Value = evaluator.evaluate(cell2); + + assertEquals(true, cell1Value.getBooleanValue()); + assertEquals(true, cell2Value.getBooleanValue()); + } +} diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestSumif.java b/src/testcases/org/apache/poi/ss/formula/functions/TestSumif.java index 6cee5eab7..c761d22f1 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestSumif.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestSumif.java @@ -21,6 +21,8 @@ import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.poi.ss.formula.eval.AreaEval; +import org.apache.poi.ss.formula.eval.BlankEval; +import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.NumberEval; import org.apache.poi.ss.formula.eval.NumericValueEval; import org.apache.poi.ss.formula.eval.StringEval; @@ -107,4 +109,11 @@ public final class TestSumif extends TestCase { confirmDouble(60, ve); } + + public void testEvaluateException() { + assertEquals(ErrorEval.VALUE_INVALID, invokeSumif(-1, -1, BlankEval.instance, new NumberEval(30.0))); + assertEquals(ErrorEval.VALUE_INVALID, invokeSumif(-1, -1, BlankEval.instance, new NumberEval(30.0), new NumberEval(30.0))); + assertEquals(ErrorEval.VALUE_INVALID, invokeSumif(-1, -1, new NumberEval(30.0), BlankEval.instance, new NumberEval(30.0))); + assertEquals(ErrorEval.VALUE_INVALID, invokeSumif(-1, -1, new NumberEval(30.0), new NumberEval(30.0), BlankEval.instance)); + } } diff --git a/src/testcases/org/apache/poi/ss/formula/functions/TestSumifs.java b/src/testcases/org/apache/poi/ss/formula/functions/TestSumifs.java index 386b521f2..3f611cb50 100644 --- a/src/testcases/org/apache/poi/ss/formula/functions/TestSumifs.java +++ b/src/testcases/org/apache/poi/ss/formula/functions/TestSumifs.java @@ -21,6 +21,7 @@ package org.apache.poi.ss.formula.functions; import junit.framework.AssertionFailedError; import junit.framework.TestCase; + import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.formula.OperationEvaluationContext; @@ -264,4 +265,84 @@ public final class TestSumifs extends TestCase { assertEquals(625000., ex5cell.getNumericCellValue()); } + + public void testBug56655() { + ValueEval[] a2a9 = new ValueEval[] { + new NumberEval(5), + new NumberEval(4), + new NumberEval(15), + new NumberEval(3), + new NumberEval(22), + new NumberEval(12), + new NumberEval(10), + new NumberEval(33) + }; + + ValueEval[] args = new ValueEval[]{ + EvalFactory.createAreaEval("A2:A9", a2a9), + ErrorEval.VALUE_INVALID, + new StringEval("A*"), + }; + + ValueEval result = invokeSumifs(args, EC); + assertTrue("Expect to have an error when an input is an invalid value, but had: " + result.getClass(), result instanceof ErrorEval); + + args = new ValueEval[]{ + EvalFactory.createAreaEval("A2:A9", a2a9), + EvalFactory.createAreaEval("A2:A9", a2a9), + ErrorEval.VALUE_INVALID, + }; + + result = invokeSumifs(args, EC); + assertTrue("Expect to have an error when an input is an invalid value, but had: " + result.getClass(), result instanceof ErrorEval); + } + + public void testBug56655b() { +/* + setCellFormula(sheet, 0, 0, "B1*C1"); + sheet.getRow(0).createCell(1).setCellValue("A"); + setCellFormula(sheet, 1, 0, "B1*C1"); + sheet.getRow(1).createCell(1).setCellValue("A"); + setCellFormula(sheet, 0, 3, "SUMIFS(A:A,A:A,A2)"); + */ + ValueEval[] a0a1 = new ValueEval[] { + NumberEval.ZERO, + NumberEval.ZERO + }; + + ValueEval[] args = new ValueEval[]{ + EvalFactory.createAreaEval("A0:A1", a0a1), + EvalFactory.createAreaEval("A0:A1", a0a1), + ErrorEval.VALUE_INVALID + }; + + ValueEval result = invokeSumifs(args, EC); + assertTrue("Expect to have an error when an input is an invalid value, but had: " + result.getClass(), result instanceof ErrorEval); + assertEquals(ErrorEval.VALUE_INVALID, result); + } + + + public void testBug56655c() { +/* + setCellFormula(sheet, 0, 0, "B1*C1"); + sheet.getRow(0).createCell(1).setCellValue("A"); + setCellFormula(sheet, 1, 0, "B1*C1"); + sheet.getRow(1).createCell(1).setCellValue("A"); + setCellFormula(sheet, 0, 3, "SUMIFS(A:A,A:A,A2)"); + */ + ValueEval[] a0a1 = new ValueEval[] { + NumberEval.ZERO, + NumberEval.ZERO + }; + + ValueEval[] args = new ValueEval[]{ + EvalFactory.createAreaEval("A0:A1", a0a1), + EvalFactory.createAreaEval("A0:A1", a0a1), + ErrorEval.NAME_INVALID + }; + + ValueEval result = invokeSumifs(args, EC); + assertTrue("Expect to have an error when an input is an invalid value, but had: " + result.getClass(), result instanceof ErrorEval); + assertEquals(ErrorEval.NAME_INVALID, result); + } } diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java index fe11df658..69cf0523e 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java @@ -18,9 +18,12 @@ package org.apache.poi.ss.usermodel; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -29,6 +32,9 @@ import org.apache.poi.hssf.util.PaneInformation; import org.apache.poi.ss.ITestDataProvider; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.SheetUtil; +import org.junit.Assume; +import org.junit.Ignore; import org.junit.Test; /** @@ -120,7 +126,7 @@ public abstract class BaseTestBugzillaIssues { * Merged regions were being removed from the parent in cloned sheets */ @Test - public final void bug22720() { + public void bug22720() { Workbook workBook = _testDataProvider.createWorkbook(); workBook.createSheet("TEST"); Sheet template = workBook.getSheetAt(0); @@ -244,7 +250,7 @@ public abstract class BaseTestBugzillaIssues { } @Test - public final void bug18800() { + public void bug18800() { Workbook book = _testDataProvider.createWorkbook(); book.createSheet("TEST"); Sheet sheet = book.cloneSheet(0); @@ -273,7 +279,7 @@ public abstract class BaseTestBugzillaIssues { } @Test - public final void bug43093() { + public void bug43093() { Workbook xlw = _testDataProvider.createWorkbook(); addNewSheetWithCellsA1toD4(xlw, 1); @@ -293,7 +299,7 @@ public abstract class BaseTestBugzillaIssues { } @Test - public final void bug46729_testMaxFunctionArguments(){ + public void bug46729_testMaxFunctionArguments(){ String[] func = {"COUNT", "AVERAGE", "MAX", "MIN", "OR", "SUBTOTAL", "SKEW"}; SpreadsheetVersion ssVersion = _testDataProvider.getSpreadsheetVersion(); @@ -332,7 +338,7 @@ public abstract class BaseTestBugzillaIssues { } @Test - public final void bug506819_testAutoSize() { + public final void bug50681_testAutoSize() { Workbook wb = _testDataProvider.createWorkbook(); BaseTestSheetAutosizeColumn.fixFonts(wb); Sheet sheet = wb.createSheet("Sheet1"); @@ -348,7 +354,26 @@ public abstract class BaseTestBugzillaIssues { cell0.setCellValue(longValue); + // autoSize will fail if required fonts are not installed, skip this test then + Font font = wb.getFontAt(cell0.getCellStyle().getFontIndex()); + Assume.assumeTrue("Cannot verify auoSizeColumn() because the necessary Fonts are not installed on this machine: " + font, + SheetUtil.canComputeColumnWidht(font)); + + assertEquals("Expecting no indentation in this test", + 0, cell0.getCellStyle().getIndention()); + + double width = SheetUtil.getColumnWidth(sheet, 0, false); + assertTrue("Expected to have column width > 0 BEFORE auto-size, but had " + width, width > 0); + width = SheetUtil.getCellWidth(cell0, 8, null, false); + assertTrue("Expected to have cell width > 0 BEFORE auto-size, but had " + width, width > 0); + sheet.autoSizeColumn(0); + + width = SheetUtil.getColumnWidth(sheet, 0, false); + assertTrue("Expected to have column width > 0 AFTER auto-size, but had " + width, width > 0); + width = SheetUtil.getCellWidth(cell0, 8, null, false); + assertTrue("Expected to have cell width > 0 AFTER auto-size, but had " + width, width > 0); + assertEquals(255*256, sheet.getColumnWidth(0)); // maximum column width is 255 characters sheet.setColumnWidth(0, sheet.getColumnWidth(0)); // Bug 506819 reports exception at this point } @@ -416,16 +441,16 @@ public abstract class BaseTestBugzillaIssues { Workbook wb = _testDataProvider.createWorkbook(); Sheet sheet = wb.createSheet("My sheet"); - Row row = sheet.createRow( 0 ); - Cell cell = row.createCell( 0 ); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); cell.setCellFormula(hyperlinkF); assertEquals(hyperlinkF, cell.getCellFormula()); wb = _testDataProvider.writeOutAndReadBack(wb); sheet = wb.getSheet("My Sheet"); - row = sheet.getRow( 0 ); - cell = row.getCell( 0 ); + row = sheet.getRow(0); + cell = row.getCell(0); assertEquals(hyperlinkF, cell.getCellFormula()); } @@ -531,7 +556,7 @@ public abstract class BaseTestBugzillaIssues { assertAlmostEquals(1950, s.getColumnWidth(10), fontAccuracy); assertAlmostEquals(2225, s.getColumnWidth(11), fontAccuracy); } - + /** * =ISNUMBER(SEARCH("AM",A1)) evaluation */ @@ -637,7 +662,7 @@ public abstract class BaseTestBugzillaIssues { // Next up, SEARCH on its own cf.setCellFormula("SEARCH(\"am\", A1)"); cf = evaluateCell(wb, cf); - assertEquals(ErrorConstants.ERROR_VALUE, cf.getErrorCellValue()); + assertEquals(FormulaError.VALUE.getCode(), cf.getErrorCellValue()); cf.setCellFormula("SEARCH(\"am\", B1)"); cf = evaluateCell(wb, cf); @@ -645,11 +670,11 @@ public abstract class BaseTestBugzillaIssues { cf.setCellFormula("SEARCH(\"am\", C1)"); cf = evaluateCell(wb, cf); - assertEquals(ErrorConstants.ERROR_VALUE, cf.getErrorCellValue()); + assertEquals(FormulaError.VALUE.getCode(), cf.getErrorCellValue()); cf.setCellFormula("SEARCH(\"am\", D1)"); cf = evaluateCell(wb, cf); - assertEquals(ErrorConstants.ERROR_VALUE, cf.getErrorCellValue()); + assertEquals(FormulaError.VALUE.getCode(), cf.getErrorCellValue()); // Finally, bring it all together @@ -688,7 +713,8 @@ public abstract class BaseTestBugzillaIssues { * TODO Fix this to evaluate for XSSF * TODO Fix this to work at all for HSSF */ -// @Test + @Ignore("Fix this to evaluate for XSSF, Fix this to work at all for HSSF") + @Test public void bug46670() throws Exception { Workbook wb = _testDataProvider.createWorkbook(); Sheet s = wb.createSheet(); @@ -727,7 +753,7 @@ public abstract class BaseTestBugzillaIssues { assertEquals(refHttp, c2.getCellFormula()); - // Try to evalutate, without giving a way to get at the other file + // Try to evaluate, without giving a way to get at the other file try { evaluateCell(wb, c1); fail("Shouldn't be able to evaluate without the other file"); @@ -757,4 +783,287 @@ public abstract class BaseTestBugzillaIssues { assertEquals(otherCellText, c1.getStringCellValue()); assertEquals(otherCellText, c2.getStringCellValue()); } + + @Test + public void test56574OverwriteExistingRow() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet = wb.createSheet(); + + { // create the Formula-Cell + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + cell.setCellFormula("A2"); + } + + { // check that it is there now + Row row = sheet.getRow(0); + + /* CTCell[] cArray = ((XSSFRow)row).getCTRow().getCArray(); + assertEquals(1, cArray.length);*/ + + Cell cell = row.getCell(0); + assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType()); + } + + { // overwrite the row + Row row = sheet.createRow(0); + assertNotNull(row); + } + + { // creating a row in place of another should remove the existing data, + // check that the cell is gone now + Row row = sheet.getRow(0); + + /*CTCell[] cArray = ((XSSFRow)row).getCTRow().getCArray(); + assertEquals(0, cArray.length);*/ + + Cell cell = row.getCell(0); + assertNull(cell); + } + + // the calculation chain in XSSF is empty in a newly created workbook, so we cannot check if it is correctly updated + /*assertNull(((XSSFWorkbook)wb).getCalculationChain()); + assertNotNull(((XSSFWorkbook)wb).getCalculationChain().getCTCalcChain()); + assertNotNull(((XSSFWorkbook)wb).getCalculationChain().getCTCalcChain().getCArray()); + assertEquals(0, ((XSSFWorkbook)wb).getCalculationChain().getCTCalcChain().getCArray().length);*/ + + wb.close(); + } + + /** + * With HSSF, if you create a font, don't change it, and + * create a 2nd, you really do get two fonts that you + * can alter as and when you want. + * With XSSF, that wasn't the case, but this verfies + * that it now is again + */ + @Test + public void bug48718() throws Exception { + Workbook wb = _testDataProvider.createWorkbook(); + int startingFonts = wb instanceof HSSFWorkbook ? 4 : 1; + + assertEquals(startingFonts, wb.getNumberOfFonts()); + + // Get a font, and slightly change it + Font a = wb.createFont(); + assertEquals(startingFonts+1, wb.getNumberOfFonts()); + a.setFontHeightInPoints((short)23); + assertEquals(startingFonts+1, wb.getNumberOfFonts()); + + // Get two more, unchanged + /*Font b =*/ wb.createFont(); + assertEquals(startingFonts+2, wb.getNumberOfFonts()); + /*Font c =*/ wb.createFont(); + assertEquals(startingFonts+3, wb.getNumberOfFonts()); + } + + @Test + public void bug57430() throws Exception { + Workbook wb = _testDataProvider.createWorkbook(); + try { + wb.createSheet("Sheet1"); + + Name name1 = wb.createName(); + name1.setNameName("FMLA"); + name1.setRefersToFormula("Sheet1!$B$3"); + } finally { + wb.close(); + } + } + + @Test + public void bug56981() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + CellStyle vertTop = wb.createCellStyle(); + vertTop.setVerticalAlignment(CellStyle.VERTICAL_TOP); + CellStyle vertBottom = wb.createCellStyle(); + vertBottom.setVerticalAlignment(CellStyle.VERTICAL_BOTTOM); + Sheet sheet = wb.createSheet("Sheet 1"); + Row row = sheet.createRow(0); + Cell top = row.createCell(0); + Cell bottom = row.createCell(1); + top.setCellValue("Top"); + top.setCellStyle(vertTop); // comment this out to get all bottom-aligned + // cells + bottom.setCellValue("Bottom"); + bottom.setCellStyle(vertBottom); + row.setHeightInPoints(85.75f); // make it obvious + + /*FileOutputStream out = new FileOutputStream("c:\\temp\\56981.xlsx"); + try { + wb.write(out); + } finally { + out.close(); + }*/ + + wb.close(); + } + + @Test + public void test57973() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + + CreationHelper factory = wb.getCreationHelper(); + + Sheet sheet = wb.createSheet(); + Drawing drawing = sheet.createDrawingPatriarch(); + ClientAnchor anchor = factory.createClientAnchor(); + + Cell cell0 = sheet.createRow(0).createCell(0); + cell0.setCellValue("Cell0"); + + Comment comment0 = drawing.createCellComment(anchor); + RichTextString str0 = factory.createRichTextString("Hello, World1!"); + comment0.setString(str0); + comment0.setAuthor("Apache POI"); + cell0.setCellComment(comment0); + + anchor = factory.createClientAnchor(); + anchor.setCol1(1); + anchor.setCol2(1); + anchor.setRow1(1); + anchor.setRow2(1); + Cell cell1 = sheet.createRow(3).createCell(5); + cell1.setCellValue("F4"); + Comment comment1 = drawing.createCellComment(anchor); + RichTextString str1 = factory.createRichTextString("Hello, World2!"); + comment1.setString(str1); + comment1.setAuthor("Apache POI"); + cell1.setCellComment(comment1); + + Cell cell2 = sheet.createRow(2).createCell(2); + cell2.setCellValue("C3"); + + anchor = factory.createClientAnchor(); + anchor.setCol1(2); + anchor.setCol2(2); + anchor.setRow1(2); + anchor.setRow2(2); + + Comment comment2 = drawing.createCellComment(anchor); + RichTextString str2 = factory.createRichTextString("XSSF can set cell comments"); + //apply custom font to the text in the comment + Font font = wb.createFont(); + font.setFontName("Arial"); + font.setFontHeightInPoints((short)14); + font.setBoldweight(Font.BOLDWEIGHT_BOLD); + font.setColor(IndexedColors.RED.getIndex()); + str2.applyFont(font); + + comment2.setString(str2); + comment2.setAuthor("Apache POI"); + comment2.setColumn(2); + comment2.setRow(2); + + /*OutputStream out = new FileOutputStream("C:\\temp\\57973.xlsx"); + try { + wb.write(out); + } finally { + out.close(); + }*/ + + wb.close(); + } + + /** + * Ensures that XSSF and HSSF agree with each other, + * and with the docs on when fetching the wrong + * kind of value from a Formula cell + */ + @Test + public void bug47815() { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet s = wb.createSheet(); + Row r = s.createRow(0); + + // Setup + Cell cn = r.createCell(0, Cell.CELL_TYPE_NUMERIC); + cn.setCellValue(1.2); + Cell cs = r.createCell(1, Cell.CELL_TYPE_STRING); + cs.setCellValue("Testing"); + + Cell cfn = r.createCell(2, Cell.CELL_TYPE_FORMULA); + cfn.setCellFormula("A1"); + Cell cfs = r.createCell(3, Cell.CELL_TYPE_FORMULA); + cfs.setCellFormula("B1"); + + FormulaEvaluator fe = wb.getCreationHelper().createFormulaEvaluator(); + assertEquals(Cell.CELL_TYPE_NUMERIC, fe.evaluate(cfn).getCellType()); + assertEquals(Cell.CELL_TYPE_STRING, fe.evaluate(cfs).getCellType()); + fe.evaluateFormulaCell(cfn); + fe.evaluateFormulaCell(cfs); + + // Now test + assertEquals(Cell.CELL_TYPE_NUMERIC, cn.getCellType()); + assertEquals(Cell.CELL_TYPE_STRING, cs.getCellType()); + assertEquals(Cell.CELL_TYPE_FORMULA, cfn.getCellType()); + assertEquals(Cell.CELL_TYPE_NUMERIC, cfn.getCachedFormulaResultType()); + assertEquals(Cell.CELL_TYPE_FORMULA, cfs.getCellType()); + assertEquals(Cell.CELL_TYPE_STRING, cfs.getCachedFormulaResultType()); + + // Different ways of retrieving + assertEquals(1.2, cn.getNumericCellValue(), 0); + try { + cn.getRichStringCellValue(); + fail(); + } catch(IllegalStateException e) {} + + assertEquals("Testing", cs.getStringCellValue()); + try { + cs.getNumericCellValue(); + fail(); + } catch(IllegalStateException e) {} + + assertEquals(1.2, cfn.getNumericCellValue(), 0); + try { + cfn.getRichStringCellValue(); + fail(); + } catch(IllegalStateException e) {} + + assertEquals("Testing", cfs.getStringCellValue()); + try { + cfs.getNumericCellValue(); + fail(); + } catch(IllegalStateException e) {} + } + + @Test + public void test58113() { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet = wb.createSheet( "Test" ); + + Row row = sheet.createRow(0); + + Cell cell = row.createCell(0); + // verify that null-values can be set, this was possible up to 3.11, but broken in 3.12 + cell.setCellValue((String)null); + String value = cell.getStringCellValue(); + assertTrue("HSSF will currently return empty string, XSSF/SXSSF will return null, but had: " + value, + value == null || value.length() == 0); + + cell = row.createCell(1); + // also verify that setting formulas to null works + cell.setCellType(Cell.CELL_TYPE_FORMULA); + cell.setCellValue((String)null); + + wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); + + value = cell.getStringCellValue(); + assertTrue("HSSF will currently return empty string, XSSF/SXSSF will return null, but had: " + value, + value == null || value.length() == 0); + + // set some value + cell.setCellType(Cell.CELL_TYPE_STRING); + cell.setCellValue("somevalue"); + + value = cell.getStringCellValue(); + assertTrue("can set value afterwards: " + value, + value.equals("somevalue")); + + // verify that the null-value is actually set even if there was some value in the cell before + cell.setCellValue((String)null); + value = cell.getStringCellValue(); + assertTrue("HSSF will currently return empty string, XSSF/SXSSF will return null, but had: " + value, + value == null || value.length() == 0); + } } diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestCell.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestCell.java index 35e95ab04..533a97397 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestCell.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestCell.java @@ -25,6 +25,7 @@ import junit.framework.TestCase; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.SpreadsheetVersion; /** * Common superclass for testing implementations of @@ -695,4 +696,75 @@ public abstract class BaseTestCell extends TestCase { wb.close(); } + + public void test57008() throws IOException { + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet = wb.createSheet(); + + Row row0 = sheet.createRow(0); + Cell cell0 = row0.createCell(0); + cell0.setCellValue("row 0, cell 0 _x0046_ without changes"); + + Cell cell1 = row0.createCell(1); + cell1.setCellValue("row 0, cell 1 _x005fx0046_ with changes"); + + Cell cell2 = row0.createCell(2); + cell2.setCellValue("hgh_x0041_**_x0100_*_x0101_*_x0190_*_x0200_*_x0300_*_x0427_*"); + + checkUnicodeValues(wb); + +// String fname = "/tmp/Test_xNNNN_inCell" + (wb instanceof HSSFWorkbook ? ".xls" : ".xlsx"); +// FileOutputStream out = new FileOutputStream(fname); +// try { +// wb.write(out); +// } finally { +// out.close(); +// } + + Workbook wbBack = _testDataProvider.writeOutAndReadBack(wb); + checkUnicodeValues(wbBack); + } + + private void checkUnicodeValues(Workbook wb) { + assertEquals((wb instanceof HSSFWorkbook ? "row 0, cell 0 _x0046_ without changes" : "row 0, cell 0 F without changes"), + wb.getSheetAt(0).getRow(0).getCell(0).toString()); + assertEquals((wb instanceof HSSFWorkbook ? "row 0, cell 1 _x005fx0046_ with changes" : "row 0, cell 1 _x005fx0046_ with changes"), + wb.getSheetAt(0).getRow(0).getCell(1).toString()); + assertEquals((wb instanceof HSSFWorkbook ? "hgh_x0041_**_x0100_*_x0101_*_x0190_*_x0200_*_x0300_*_x0427_*" : "hghA**\u0100*\u0101*\u0190*\u0200*\u0300*\u0427*"), + wb.getSheetAt(0).getRow(0).getCell(2).toString()); + } + + /** + * The maximum length of cell contents (text) is 32,767 characters. + * @throws IOException + */ + public void testMaxTextLength() throws IOException{ + Workbook wb = _testDataProvider.createWorkbook(); + Sheet sheet = wb.createSheet(); + Cell cell = sheet.createRow(0).createCell(0); + + int maxlen = wb instanceof HSSFWorkbook ? + SpreadsheetVersion.EXCEL97.getMaxTextLength() + : SpreadsheetVersion.EXCEL2007.getMaxTextLength(); + assertEquals(32767, maxlen); + + StringBuffer b = new StringBuffer() ; + + // 32767 is okay + for( int i = 0 ; i < maxlen ; i++ ) + { + b.append( "X" ) ; + } + cell.setCellValue(b.toString()); + + b.append("X"); + // 32768 produces an invalid XLS file + try { + cell.setCellValue(b.toString()); + fail("Expected exception"); + } catch (IllegalArgumentException e){ + assertEquals("The maximum length of cell contents (text) is 32,767 characters", e.getMessage()); + } + wb.close(); + } } diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java index b6e6ca932..b8eeb2053 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java +++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestConditionalFormatting.java @@ -20,12 +20,16 @@ package org.apache.poi.ss.usermodel; import junit.framework.TestCase; + +import org.apache.poi.hssf.usermodel.HSSFConditionalFormatting; +import org.apache.poi.hssf.usermodel.HSSFConditionalFormattingRule; import org.apache.poi.ss.ITestDataProvider; +import org.apache.poi.ss.usermodel.ConditionalFormattingThreshold.RangeType; +import org.apache.poi.ss.usermodel.IconMultiStateFormatting.IconSet; import org.apache.poi.ss.util.CellRangeAddress; /** - * @author Dmitriy Kumshayev - * @author Yegor Kozlov + * Base tests for Conditional Formatting, for both HSSF and XSSF */ public abstract class BaseTestConditionalFormatting extends TestCase { private final ITestDataProvider _testDataProvider; @@ -33,6 +37,8 @@ public abstract class BaseTestConditionalFormatting extends TestCase { public BaseTestConditionalFormatting(ITestDataProvider testDataProvider){ _testDataProvider = testDataProvider; } + + protected abstract void assertColour(String hexExpected, Color actual); public void testBasic() { Workbook wb = _testDataProvider.createWorkbook(); @@ -101,7 +107,8 @@ public abstract class BaseTestConditionalFormatting extends TestCase { SheetConditionalFormatting sheetCF = sh.getSheetConditionalFormatting(); ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule("SUM(A1:A5)>10"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_FORMULA, rule1.getConditionType()); + assertEquals(ConditionType.FORMULA.id, rule1.getConditionType()); + assertEquals(ConditionType.FORMULA, rule1.getConditionTypeType()); assertEquals("SUM(A1:A5)>10", rule1.getFormula1()); int formatIndex1 = sheetCF.addConditionalFormatting( new CellRangeAddress[]{ @@ -136,56 +143,65 @@ public abstract class BaseTestConditionalFormatting extends TestCase { ConditionalFormattingRule rule1 = sheetCF.createConditionalFormattingRule( ComparisonOperator.EQUAL, "SUM(A1:A5)+10"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule1.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule1.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule1.getConditionTypeType()); assertEquals("SUM(A1:A5)+10", rule1.getFormula1()); assertEquals(ComparisonOperator.EQUAL, rule1.getComparisonOperation()); ConditionalFormattingRule rule2 = sheetCF.createConditionalFormattingRule( ComparisonOperator.NOT_EQUAL, "15"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule2.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule2.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule2.getConditionTypeType()); assertEquals("15", rule2.getFormula1()); assertEquals(ComparisonOperator.NOT_EQUAL, rule2.getComparisonOperation()); ConditionalFormattingRule rule3 = sheetCF.createConditionalFormattingRule( ComparisonOperator.NOT_EQUAL, "15"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule3.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule3.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule3.getConditionTypeType()); assertEquals("15", rule3.getFormula1()); assertEquals(ComparisonOperator.NOT_EQUAL, rule3.getComparisonOperation()); ConditionalFormattingRule rule4 = sheetCF.createConditionalFormattingRule( ComparisonOperator.GT, "0"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule4.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule4.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule4.getConditionTypeType()); assertEquals("0", rule4.getFormula1()); assertEquals(ComparisonOperator.GT, rule4.getComparisonOperation()); ConditionalFormattingRule rule5 = sheetCF.createConditionalFormattingRule( ComparisonOperator.LT, "0"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule5.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule5.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule5.getConditionTypeType()); assertEquals("0", rule5.getFormula1()); assertEquals(ComparisonOperator.LT, rule5.getComparisonOperation()); ConditionalFormattingRule rule6 = sheetCF.createConditionalFormattingRule( ComparisonOperator.GE, "0"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule6.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule6.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule6.getConditionTypeType()); assertEquals("0", rule6.getFormula1()); assertEquals(ComparisonOperator.GE, rule6.getComparisonOperation()); ConditionalFormattingRule rule7 = sheetCF.createConditionalFormattingRule( ComparisonOperator.LE, "0"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule7.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule7.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule7.getConditionTypeType()); assertEquals("0", rule7.getFormula1()); assertEquals(ComparisonOperator.LE, rule7.getComparisonOperation()); ConditionalFormattingRule rule8 = sheetCF.createConditionalFormattingRule( ComparisonOperator.BETWEEN, "0", "5"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule8.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule8.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule8.getConditionTypeType()); assertEquals("0", rule8.getFormula1()); assertEquals("5", rule8.getFormula2()); assertEquals(ComparisonOperator.BETWEEN, rule8.getComparisonOperation()); ConditionalFormattingRule rule9 = sheetCF.createConditionalFormattingRule( ComparisonOperator.NOT_BETWEEN, "0", "5"); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule9.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS.id, rule9.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule9.getConditionTypeType()); assertEquals("0", rule9.getFormula1()); assertEquals("5", rule9.getFormula2()); assertEquals(ComparisonOperator.NOT_BETWEEN, rule9.getComparisonOperation()); @@ -455,7 +471,7 @@ public abstract class BaseTestConditionalFormatting extends TestCase { // CF1 has two rules: values less than -3 are bold-italic red, values greater than 3 are green ConditionalFormattingRule rule1 = cf1.getRule(0); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule1.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule1.getConditionTypeType()); assertEquals(ComparisonOperator.GT, rule1.getComparisonOperation()); assertEquals("3", rule1.getFormula1()); assertNull(rule1.getFormula2()); @@ -469,7 +485,7 @@ public abstract class BaseTestConditionalFormatting extends TestCase { assertFalse(fmt1.isItalic()); ConditionalFormattingRule rule2 = cf1.getRule(1); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule2.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule2.getConditionTypeType()); assertEquals(ComparisonOperator.LT, rule2.getComparisonOperation()); assertEquals("-3", rule2.getFormula1()); assertNull(rule2.getFormula2()); @@ -489,7 +505,7 @@ public abstract class BaseTestConditionalFormatting extends TestCase { assertEquals("B9", regions2[0].formatAsString()); ConditionalFormattingRule rule3 = cf2.getRule(0); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_FORMULA, rule3.getConditionType()); + assertEquals(ConditionType.FORMULA, rule3.getConditionTypeType()); assertEquals(ComparisonOperator.NO_COMPARISON, rule3.getComparisonOperation()); assertEquals("$A$8>5", rule3.getFormula1()); assertNull(rule3.getFormula2()); @@ -513,18 +529,210 @@ public abstract class BaseTestConditionalFormatting extends TestCase { assertEquals(2, cf3.getNumberOfRules()); ConditionalFormattingRule rule4 = cf3.getRule(0); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule4.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule4.getConditionTypeType()); assertEquals(ComparisonOperator.LE, rule4.getComparisonOperation()); assertEquals("\"AAA\"", rule4.getFormula1()); assertNull(rule4.getFormula2()); ConditionalFormattingRule rule5 = cf3.getRule(1); - assertEquals(ConditionalFormattingRule.CONDITION_TYPE_CELL_VALUE_IS, rule5.getConditionType()); + assertEquals(ConditionType.CELL_VALUE_IS, rule5.getConditionTypeType()); assertEquals(ComparisonOperator.BETWEEN, rule5.getComparisonOperation()); assertEquals("\"A\"", rule5.getFormula1()); assertEquals("\"AAA\"", rule5.getFormula2()); } + public void testReadOffice2007(String filename) { + Workbook wb = _testDataProvider.openSampleWorkbook(filename); + Sheet s = wb.getSheet("CF"); + ConditionalFormatting cf = null; + ConditionalFormattingRule cr = null; + IconMultiStateFormatting icon = null; + ConditionalFormattingThreshold th = null; + + // Sanity check data + assertEquals("Values", s.getRow(0).getCell(0).toString()); + assertEquals("10.0", s.getRow(2).getCell(0).toString()); + + // Check we found all the conditional formattings rules we should have + SheetConditionalFormatting sheetCF = s.getSheetConditionalFormatting(); + int numCF = 3; + int numCF12 = 15; + int numCFEX = 0; // TODO This should be 1, but we don't support CFEX formattings yet + assertEquals(numCF+numCF12+numCFEX, sheetCF.getNumConditionalFormattings()); + + int fCF = 0, fCF12 = 0, fCFEX = 0; + for (int i=0; iG - Column F + cf = sheetCF.getConditionalFormattingAt(3); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("F2:F17", cf.getFormattingRanges()[0].formatAsString()); + + assertEquals(1, cf.getNumberOfRules()); + cr = cf.getRule(0); + assertEquals(ConditionType.COLOR_SCALE, cr.getConditionTypeType()); + // TODO Support Color Scales, then check the rest of this rule + + + // Colours BWR - Column G + cf = sheetCF.getConditionalFormattingAt(4); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("G2:G17", cf.getFormattingRanges()[0].formatAsString()); + + assertEquals(1, cf.getNumberOfRules()); + cr = cf.getRule(0); + assertEquals(ConditionType.COLOR_SCALE, cr.getConditionTypeType()); + // TODO Support Color Scales, then check the rest of this rule + + + // Icons : Default - Column H, percentage thresholds + cf = sheetCF.getConditionalFormattingAt(5); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("H2:H17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_TRAFFIC_LIGHTS, 0d, 33d, 67d); + + + // Icons : 3 signs - Column I + cf = sheetCF.getConditionalFormattingAt(6); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("I2:I17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_SHAPES, 0d, 33d, 67d); + + + // Icons : 3 traffic lights 2 - Column J + cf = sheetCF.getConditionalFormattingAt(7); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("J2:J17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYR_3_TRAFFIC_LIGHTS_BOX, 0d, 33d, 67d); + + + // Icons : 4 traffic lights - Column K + cf = sheetCF.getConditionalFormattingAt(8); + assertEquals(1, cf.getFormattingRanges().length); + assertEquals("K2:K17", cf.getFormattingRanges()[0].formatAsString()); + assertIconSetPercentages(cf, IconSet.GYRB_4_TRAFFIC_LIGHTS, 0d, 25d, 50d, 75d); + + + // Icons : 3 symbols - Column L + // Icons : 3 flags - Column M + // Icons : 3 symbols 2 - Column N + // Icons : 3 arrows - Column O + // Icons : 5 arrows grey - Column P + // Icons : 3 stars (ext) - Column Q + // Icons : 4 ratings - Column R + // Icons : 5 ratings - Column S + // Custom Icon+Format - Column T + // Mixed icons - Column U + + } + private void assertIconSetPercentages(ConditionalFormatting cf, IconSet iconset, Double...vals) { + assertEquals(1, cf.getNumberOfRules()); + ConditionalFormattingRule cr = cf.getRule(0); + + assertEquals(ConditionType.ICON_SET, cr.getConditionTypeType()); + assertEquals(ComparisonOperator.NO_COMPARISON, cr.getComparisonOperation()); + assertEquals(null, cr.getFormula1()); + assertEquals(null, cr.getFormula2()); + + IconMultiStateFormatting icon = cr.getMultiStateFormatting(); + assertNotNull(icon); + assertEquals(iconset, icon.getIconSet()); + assertEquals(false, icon.isIconOnly()); + assertEquals(false, icon.isReversed()); + + assertNotNull(icon.getThresholds()); + assertEquals(vals.length, icon.getThresholds().length); + for (int i=0; i 0); + + wb.close(); + } + + public void testGetCellWidthNumber() throws IOException { + Workbook wb = new HSSFWorkbook(); + Sheet sheet = wb.createSheet("sheet"); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + + cell.setCellValue(88.234); + + assertTrue(SheetUtil.getCellWidth(cell, 1, null, true) > 0); + + wb.close(); + } + + public void testGetCellWidthBoolean() throws IOException { + Workbook wb = new HSSFWorkbook(); + Sheet sheet = wb.createSheet("sheet"); + Row row = sheet.createRow(0); + Cell cell = row.createCell(0); + + cell.setCellValue(false); + + assertTrue(SheetUtil.getCellWidth(cell, 1, null, false) > 0); + + wb.close(); + } + + public void testGetColumnWidthString() throws IOException { + Workbook wb = new HSSFWorkbook(); + Sheet sheet = wb.createSheet("sheet"); + Row row = sheet.createRow(0); + sheet.createRow(1); + sheet.createRow(2); + Cell cell = row.createCell(0); + + cell.setCellValue("sometext"); + + assertTrue("Having some width for rows with actual cells", + SheetUtil.getColumnWidth(sheet, 0, true) > 0); + assertEquals("Not having any widht for rows with all empty cells", + -1.0, SheetUtil.getColumnWidth(sheet, 0, true, 1, 2)); + + wb.close(); + } +} diff --git a/src/testcases/org/apache/poi/util/AllPOIUtilTests.java b/src/testcases/org/apache/poi/util/AllPOIUtilTests.java index de6739bb7..34ad0f4bd 100644 --- a/src/testcases/org/apache/poi/util/AllPOIUtilTests.java +++ b/src/testcases/org/apache/poi/util/AllPOIUtilTests.java @@ -17,30 +17,29 @@ package org.apache.poi.util; -import junit.framework.Test; -import junit.framework.TestSuite; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; /** * Test suite for all sub-packages of org.apache.poi.util
    */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + TestArrayUtil.class + , TestBinaryTree.class + , TestBitField.class + , TestByteField.class + , TestHexDump.class + , TestIntegerField.class + , TestIntList.class + , TestLittleEndian.class + , TestLongField.class + , TestPOILogFactory.class + , TestPOILogger.class + , TestShortField.class + , TestShortList.class + , TestStringUtil.class + , TestTempFile.class +}) public final class AllPOIUtilTests { - public static Test suite() { - TestSuite result = new TestSuite(AllPOIUtilTests.class.getName()); - result.addTestSuite(TestArrayUtil.class); - result.addTestSuite(TestBinaryTree.class); - result.addTestSuite(TestBitField.class); - result.addTestSuite(TestByteField.class); - result.addTestSuite(TestHexDump.class); - result.addTestSuite(TestIntegerField.class); - result.addTestSuite(TestIntList.class); - result.addTestSuite(TestLittleEndian.class); - result.addTestSuite(TestLongField.class); - result.addTestSuite(TestPOILogFactory.class); - result.addTestSuite(TestPOILogger.class); - result.addTestSuite(TestShortField.class); - result.addTestSuite(TestShortList.class); - result.addTestSuite(TestStringUtil.class); - result.addTestSuite(TestTempFile.class); - return result; - } } diff --git a/src/testcases/org/apache/poi/util/TestPOILogger.java b/src/testcases/org/apache/poi/util/TestPOILogger.java index a3d34fac1..7fc5824d4 100644 --- a/src/testcases/org/apache/poi/util/TestPOILogger.java +++ b/src/testcases/org/apache/poi/util/TestPOILogger.java @@ -18,7 +18,13 @@ package org.apache.poi.util; -import junit.framework.TestCase; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Field; + +import org.junit.Test; /** * Tests the log class. @@ -27,23 +33,62 @@ import junit.framework.TestCase; * @author Marc Johnson (mjohnson at apache dot org) * @author Nicola Ken Barozzi (nicolaken at apache.org) */ -public final class TestPOILogger extends TestCase { - +public final class TestPOILogger extends POILogger { + private String lastLog = ""; + private Throwable lastEx = null; + /** * Test different types of log output. */ - public void testVariousLogTypes() { - //NKB Testing only that logging classes use gives no exception - // Since logging can be disabled, no checking of logging - // output is done. + @Test + public void testVariousLogTypes() throws Exception { + Field f = POILogFactory.class.getDeclaredField("_loggerClassName"); + f.setAccessible(true); + String oldLCN = (String)f.get(null); + try { + f.set(null, TestPOILogger.class.getName()); + POILogger log = POILogFactory.getLogger( "foo" ); + assertTrue(log instanceof TestPOILogger); + + TestPOILogger tlog = (TestPOILogger)log; + + log.log(POILogger.WARN, "Test = ", 1); + assertEquals("Test = 1", tlog.lastLog); + + log.logFormatted(POILogger.ERROR, "Test param 1 = %, param 2 = %d", "2", 3 ); + assertEquals("Test param 1 = 2, param 2 = 3", tlog.lastLog); + + log.logFormatted(POILogger.ERROR, "Test param 1 = %d, param 2 = %", new int[]{4, 5} ); + assertEquals("Test param 1 = 4, param 2 = 5", tlog.lastLog); + + log.logFormatted(POILogger.ERROR, "Test param 1 = %1.1, param 2 = %0.1", new double[]{4, 5.23} ); + assertEquals("Test param 1 = 4, param 2 = 5.2", tlog.lastLog); - POILogger log = POILogFactory.getLogger( "foo" ); + log.log(POILogger.ERROR, "Test ", 1,2,new Exception("bla")); + assertEquals("Test 12", tlog.lastLog); + assertNotNull(tlog.lastEx); + + log.log(POILogger.ERROR, "log\nforging", "\nevil","\nlog"); + assertEquals("log forging evil log", tlog.lastLog); + } finally { + f.set(null, oldLCN); + } + } - log.log( POILogger.WARN, "Test = ", Integer.valueOf( 1 ) ); - log.logFormatted( POILogger.ERROR, "Test param 1 = %, param 2 = %", "2", Integer.valueOf( 3 ) ); - log.logFormatted( POILogger.ERROR, "Test param 1 = %, param 2 = %", new int[]{4, 5} ); - log.logFormatted( POILogger.ERROR, - "Test param 1 = %1.1, param 2 = %0.1", new double[]{4, 5.23} ); + public void initialize(String cat) { + } + public void log(int level, Object obj1) { + lastLog = (obj1 == null) ? "" : obj1.toString(); + lastEx = null; + } + + public void log(int level, Object obj1, Throwable exception) { + lastLog = (obj1 == null) ? "" : obj1.toString(); + lastEx = exception; + } + + public boolean check(int level) { + return true; } } diff --git a/test-data/diagram/44501a.vsd b/test-data/diagram/44501a.vsd new file mode 100755 index 000000000..7d9a3cefc Binary files /dev/null and b/test-data/diagram/44501a.vsd differ diff --git a/test-data/diagram/44501b.vsd b/test-data/diagram/44501b.vsd new file mode 100755 index 000000000..c8bd7a190 Binary files /dev/null and b/test-data/diagram/44501b.vsd differ diff --git a/test-data/diagram/44501c.vsd b/test-data/diagram/44501c.vsd new file mode 100644 index 000000000..51de23a32 Binary files /dev/null and b/test-data/diagram/44501c.vsd differ diff --git a/test-data/diagram/44501d.vsd b/test-data/diagram/44501d.vsd new file mode 100755 index 000000000..2c1632eba Binary files /dev/null and b/test-data/diagram/44501d.vsd differ diff --git a/test-data/diagram/44501e.vsd b/test-data/diagram/44501e.vsd new file mode 100644 index 000000000..3ca555230 Binary files /dev/null and b/test-data/diagram/44501e.vsd differ diff --git a/test-data/diagram/test.vsdx b/test-data/diagram/test.vsdx new file mode 100644 index 000000000..1fa690356 Binary files /dev/null and b/test-data/diagram/test.vsdx differ diff --git a/test-data/document/47304.doc b/test-data/document/47304.doc new file mode 100644 index 000000000..d59d8d7ee Binary files /dev/null and b/test-data/document/47304.doc differ diff --git a/test-data/document/51921-Word-Crash067.doc b/test-data/document/51921-Word-Crash067.doc new file mode 100644 index 000000000..dc8bfff27 Binary files /dev/null and b/test-data/document/51921-Word-Crash067.doc differ diff --git a/test-data/document/51921-Word-Crash067.docx b/test-data/document/51921-Word-Crash067.docx new file mode 100644 index 000000000..12c27c85e Binary files /dev/null and b/test-data/document/51921-Word-Crash067.docx differ diff --git a/test-data/document/52117.doc b/test-data/document/52117.doc new file mode 100644 index 000000000..4f966c01c Binary files /dev/null and b/test-data/document/52117.doc differ diff --git a/test-data/document/53379.doc b/test-data/document/53379.doc new file mode 100644 index 000000000..5f1b3bde4 Binary files /dev/null and b/test-data/document/53379.doc differ diff --git a/test-data/document/56392.docx b/test-data/document/56392.docx new file mode 100644 index 000000000..89a71aed2 Binary files /dev/null and b/test-data/document/56392.docx differ diff --git a/test-data/document/Numbering.docx b/test-data/document/Numbering.docx index da0f32572..d5605c9f7 100644 Binary files a/test-data/document/Numbering.docx and b/test-data/document/Numbering.docx differ diff --git a/test-data/document/NumberingWOverrides.docx b/test-data/document/NumberingWOverrides.docx new file mode 100644 index 000000000..48a7e2c25 Binary files /dev/null and b/test-data/document/NumberingWOverrides.docx differ diff --git a/test-data/document/au.edu.utas.www___data_assets_word_doc_0003_154335_International-Travel-Approval-Request-Form.doc b/test-data/document/au.edu.utas.www___data_assets_word_doc_0003_154335_International-Travel-Approval-Request-Form.doc new file mode 100644 index 000000000..82d00415e Binary files /dev/null and b/test-data/document/au.edu.utas.www___data_assets_word_doc_0003_154335_International-Travel-Approval-Request-Form.doc differ diff --git a/test-data/document/zero-length.docx b/test-data/document/zero-length.docx new file mode 100644 index 000000000..eb34b47b1 Binary files /dev/null and b/test-data/document/zero-length.docx differ diff --git a/test-data/hsmf/message_1979.msg b/test-data/hsmf/message_1979.msg new file mode 100644 index 000000000..10083c8e4 Binary files /dev/null and b/test-data/hsmf/message_1979.msg differ diff --git a/test-data/hsmf/message_1980.msg b/test-data/hsmf/message_1980.msg new file mode 100644 index 000000000..bb295404d Binary files /dev/null and b/test-data/hsmf/message_1980.msg differ diff --git a/test-data/hsmf/message_1981.msg b/test-data/hsmf/message_1981.msg new file mode 100644 index 000000000..6833d5434 Binary files /dev/null and b/test-data/hsmf/message_1981.msg differ diff --git a/test-data/hsmf/message_extra_hyphen_submission_chunk.msg b/test-data/hsmf/message_extra_hyphen_submission_chunk.msg new file mode 100644 index 000000000..3bcb8d363 Binary files /dev/null and b/test-data/hsmf/message_extra_hyphen_submission_chunk.msg differ diff --git a/test-data/hsmf/message_normal_submission_chunk.msg b/test-data/hsmf/message_normal_submission_chunk.msg new file mode 100644 index 000000000..bb15d2746 Binary files /dev/null and b/test-data/hsmf/message_normal_submission_chunk.msg differ diff --git a/test-data/openxml4j/OPCCompliance_NoCoreProperties.xlsx b/test-data/openxml4j/OPCCompliance_NoCoreProperties.xlsx new file mode 100644 index 000000000..fa1049c68 Binary files /dev/null and b/test-data/openxml4j/OPCCompliance_NoCoreProperties.xlsx differ diff --git a/test-data/poifs/only-zero-byte-streams.ole2 b/test-data/poifs/only-zero-byte-streams.ole2 new file mode 100644 index 000000000..c1b842987 Binary files /dev/null and b/test-data/poifs/only-zero-byte-streams.ole2 differ diff --git a/test-data/poifs/unknown_properties.msg b/test-data/poifs/unknown_properties.msg new file mode 100644 index 000000000..2c76df98e Binary files /dev/null and b/test-data/poifs/unknown_properties.msg differ diff --git a/test-data/slideshow/54332a.ppt b/test-data/slideshow/54332a.ppt new file mode 100644 index 000000000..ebdedf5e3 Binary files /dev/null and b/test-data/slideshow/54332a.ppt differ diff --git a/test-data/slideshow/54332b.ppt b/test-data/slideshow/54332b.ppt new file mode 100644 index 000000000..41f20fa55 Binary files /dev/null and b/test-data/slideshow/54332b.ppt differ diff --git a/test-data/slideshow/ae.ac.uaeu.faculty_nafaachbili_GeomLec1.pptx b/test-data/slideshow/ae.ac.uaeu.faculty_nafaachbili_GeomLec1.pptx new file mode 100644 index 000000000..ca9d7919c Binary files /dev/null and b/test-data/slideshow/ae.ac.uaeu.faculty_nafaachbili_GeomLec1.pptx differ diff --git a/test-data/slideshow/at.ecodesign.www_downloads_Vertiefungsvortrag_elektronik.pptx b/test-data/slideshow/at.ecodesign.www_downloads_Vertiefungsvortrag_elektronik.pptx new file mode 100644 index 000000000..057886216 Binary files /dev/null and b/test-data/slideshow/at.ecodesign.www_downloads_Vertiefungsvortrag_elektronik.pptx differ diff --git a/test-data/slideshow/bug57820-initTableNullRefrenceException.ppt b/test-data/slideshow/bug57820-initTableNullRefrenceException.ppt new file mode 100644 index 000000000..e7525f945 Binary files /dev/null and b/test-data/slideshow/bug57820-initTableNullRefrenceException.ppt differ diff --git a/test-data/spreadsheet/49423.xls b/test-data/spreadsheet/49423.xls new file mode 100644 index 000000000..3d8524cba Binary files /dev/null and b/test-data/spreadsheet/49423.xls differ diff --git a/test-data/spreadsheet/53109.xls b/test-data/spreadsheet/53109.xls new file mode 100644 index 000000000..08b4dfeec Binary files /dev/null and b/test-data/spreadsheet/53109.xls differ diff --git a/test-data/spreadsheet/56295.xlsx b/test-data/spreadsheet/56295.xlsx new file mode 100644 index 000000000..d929d99a1 Binary files /dev/null and b/test-data/spreadsheet/56295.xlsx differ diff --git a/test-data/spreadsheet/56325a.xls b/test-data/spreadsheet/56325a.xls new file mode 100644 index 000000000..a1e52cb5d Binary files /dev/null and b/test-data/spreadsheet/56325a.xls differ diff --git a/test-data/spreadsheet/56574.xlsx b/test-data/spreadsheet/56574.xlsx new file mode 100644 index 000000000..9cce54cc8 Binary files /dev/null and b/test-data/spreadsheet/56574.xlsx differ diff --git a/test-data/spreadsheet/57163.xls b/test-data/spreadsheet/57163.xls new file mode 100644 index 000000000..402c954e1 Binary files /dev/null and b/test-data/spreadsheet/57163.xls differ diff --git a/test-data/spreadsheet/57423.xlsx b/test-data/spreadsheet/57423.xlsx new file mode 100644 index 000000000..54c65be52 Binary files /dev/null and b/test-data/spreadsheet/57423.xlsx differ diff --git a/test-data/spreadsheet/57826.xlsx b/test-data/spreadsheet/57826.xlsx new file mode 100644 index 000000000..ccf2dc38f Binary files /dev/null and b/test-data/spreadsheet/57826.xlsx differ diff --git a/test-data/spreadsheet/57828.xlsx b/test-data/spreadsheet/57828.xlsx new file mode 100644 index 000000000..c750a0944 Binary files /dev/null and b/test-data/spreadsheet/57828.xlsx differ diff --git a/test-data/spreadsheet/57893-many-merges.xlsx b/test-data/spreadsheet/57893-many-merges.xlsx new file mode 100644 index 000000000..572dfec27 Binary files /dev/null and b/test-data/spreadsheet/57893-many-merges.xlsx differ diff --git a/test-data/spreadsheet/NewStyleConditionalFormattings.xls b/test-data/spreadsheet/NewStyleConditionalFormattings.xls new file mode 100644 index 000000000..fdb241b01 Binary files /dev/null and b/test-data/spreadsheet/NewStyleConditionalFormattings.xls differ diff --git a/test-data/spreadsheet/NewStyleConditionalFormattings.xlsx b/test-data/spreadsheet/NewStyleConditionalFormattings.xlsx new file mode 100644 index 000000000..93c034f0b Binary files /dev/null and b/test-data/spreadsheet/NewStyleConditionalFormattings.xlsx differ diff --git a/test-data/spreadsheet/SampleSS.strict.xlsx b/test-data/spreadsheet/SampleSS.strict.xlsx new file mode 100644 index 000000000..6bf19368e Binary files /dev/null and b/test-data/spreadsheet/SampleSS.strict.xlsx differ diff --git a/test-data/spreadsheet/SimpleNormal.xlsx b/test-data/spreadsheet/SimpleNormal.xlsx new file mode 100644 index 000000000..35378c724 Binary files /dev/null and b/test-data/spreadsheet/SimpleNormal.xlsx differ diff --git a/test-data/spreadsheet/SimpleStrict.xlsx b/test-data/spreadsheet/SimpleStrict.xlsx new file mode 100644 index 000000000..7ed3e45d2 Binary files /dev/null and b/test-data/spreadsheet/SimpleStrict.xlsx differ diff --git a/test-data/spreadsheet/ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls b/test-data/spreadsheet/ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls new file mode 100644 index 000000000..5554ab9f9 Binary files /dev/null and b/test-data/spreadsheet/ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls differ diff --git a/test-data/spreadsheet/com.aida-tour.www_SPO_files_maldives%20august%20october.xls b/test-data/spreadsheet/com.aida-tour.www_SPO_files_maldives%20august%20october.xls new file mode 100644 index 000000000..90b0bd65e Binary files /dev/null and b/test-data/spreadsheet/com.aida-tour.www_SPO_files_maldives%20august%20october.xls differ diff --git a/test-data/spreadsheet/protected_passtika.xlsx b/test-data/spreadsheet/protected_passtika.xlsx new file mode 100644 index 000000000..deea286c6 Binary files /dev/null and b/test-data/spreadsheet/protected_passtika.xlsx differ diff --git a/test-data/spreadsheet/sample.strict.xlsx b/test-data/spreadsheet/sample.strict.xlsx new file mode 100644 index 000000000..9c6c8f15d Binary files /dev/null and b/test-data/spreadsheet/sample.strict.xlsx differ