diff --git a/rome-modules/src/main/java/com/rometools/modules/mediarss/io/MediaModuleParser.java b/rome-modules/src/main/java/com/rometools/modules/mediarss/io/MediaModuleParser.java index 2cfa573..c670a7a 100644 --- a/rome-modules/src/main/java/com/rometools/modules/mediarss/io/MediaModuleParser.java +++ b/rome-modules/src/main/java/com/rometools/modules/mediarss/io/MediaModuleParser.java @@ -21,10 +21,13 @@ */ package com.rometools.modules.mediarss.io; +import java.math.BigDecimal; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.StringTokenizer; import org.jdom2.Element; @@ -65,6 +68,8 @@ public class MediaModuleParser implements ModuleParser { private static final Namespace NS = Namespace.getNamespace(MediaModule.URI); + private static final Pattern FILESIZE_WITH_UNIT_PATTERN = Pattern.compile("([\\d,.]+)([TGMK])?B", Pattern.CASE_INSENSITIVE); + @Override public String getNamespaceUri() { return MediaModule.URI; @@ -92,6 +97,35 @@ public class MediaModuleParser implements ModuleParser { return mod; } + static long parseFileSize(String fileSizeAttrValue) { + String nonWSFileSize = fileSizeAttrValue.replaceAll("\\s", ""); + + if(nonWSFileSize.matches("\\d+")) { + return Long.valueOf(nonWSFileSize); + } + + Matcher sizeWithUnitMatcher = FILESIZE_WITH_UNIT_PATTERN.matcher(nonWSFileSize); + if (sizeWithUnitMatcher.matches()) { + BigDecimal number = new BigDecimal(sizeWithUnitMatcher.group(1).replace(',', '.')); + BigDecimal multiplier = BigDecimal.valueOf(1); + if (sizeWithUnitMatcher.group(2) != null) { + char unit = sizeWithUnitMatcher.group(2).toLowerCase().charAt(0); + if (unit == 'k') { + multiplier = BigDecimal.valueOf(1000); + } else if (unit == 'm') { + multiplier = BigDecimal.valueOf(1000).pow(2); + } else if (unit == 'g') { + multiplier = BigDecimal.valueOf(1000).pow(3); + } else if (unit == 't') { + multiplier = BigDecimal.valueOf(1000).pow(4); + } + } + return number.multiply(multiplier).longValue(); + } + + throw new NumberFormatException("Invalid file size: " + fileSizeAttrValue); + } + private MediaContent[] parseContent(final Element e) { final List contents = e.getChildren("content", getNS()); @@ -152,7 +186,7 @@ public class MediaModuleParser implements ModuleParser { try { if (content.getAttributeValue("fileSize") != null) { - mc.setFileSize(Long.valueOf(content.getAttributeValue("fileSize"))); + mc.setFileSize(parseFileSize(content.getAttributeValue("fileSize"))); } } catch (final Exception ex) { LOG.warn("Exception parsing content tag.", ex); diff --git a/rome-modules/src/test/java/com/rometools/modules/mediarss/MediaModuleTest.java b/rome-modules/src/test/java/com/rometools/modules/mediarss/MediaModuleTest.java index f53a68f..a8e925a 100644 --- a/rome-modules/src/test/java/com/rometools/modules/mediarss/MediaModuleTest.java +++ b/rome-modules/src/test/java/com/rometools/modules/mediarss/MediaModuleTest.java @@ -15,14 +15,13 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.math.BigDecimal; import java.util.List; import junit.framework.Test; import junit.framework.TestSuite; import com.rometools.modules.AbstractTestCase; -import com.rometools.modules.mediarss.MediaEntryModule; -import com.rometools.modules.mediarss.MediaModule; import com.rometools.modules.mediarss.types.MediaContent; import com.rometools.modules.mediarss.types.Rating; import com.rometools.modules.mediarss.types.Thumbnail; @@ -91,6 +90,16 @@ public class MediaModuleTest extends AbstractTestCase { } } + + public void testParseFileSizeWithUnits() throws Exception { + final SyndFeed feed = getSyndFeed("org/rometools/feed/module/mediarss/filesize-with-unit.xml"); + final List entries = feed.getEntries(); + + final MediaEntryModule module = (MediaEntryModule) entries.get(0).getModule(MediaModule.URI); + Long parsedFileSize = module.getMediaContents()[0].getFileSize(); + assertThat(parsedFileSize, is(new BigDecimal(1000).pow(3).longValue())); + } + /** * tests parsing thubnails with empty dimensions * (https://github.com/rometools/rome-modules/issues/7). diff --git a/rome-modules/src/test/java/com/rometools/modules/mediarss/io/MediaModuleParserTest.java b/rome-modules/src/test/java/com/rometools/modules/mediarss/io/MediaModuleParserTest.java new file mode 100644 index 0000000..c87b77d --- /dev/null +++ b/rome-modules/src/test/java/com/rometools/modules/mediarss/io/MediaModuleParserTest.java @@ -0,0 +1,74 @@ +/* + * Licensed 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 com.rometools.modules.mediarss.io; + +import com.rometools.modules.AbstractTestCase; +import junit.framework.Test; +import junit.framework.TestSuite; + +import java.math.BigDecimal; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class MediaModuleParserTest extends AbstractTestCase { + + public MediaModuleParserTest(String testName) { + super(testName); + } + + public static Test suite() { + return new TestSuite(MediaModuleParserTest.class); + } + + public void testParsesFileSizeWithoutUnit() { + assertThat(MediaModuleParser.parseFileSize("1234567"), is(1234567L)); + } + + public void testParsesFileSizeWithByteUnit() { + assertThat(MediaModuleParser.parseFileSize("1B"), is(1L)); + } + + public void testParsesFileSizeWithKiloByteUnit() { + assertThat(MediaModuleParser.parseFileSize("1KB"), is(1000L)); + } + + public void testParsesFileSizeWithMegaByteUnit() { + assertThat(MediaModuleParser.parseFileSize("1MB"), is(new BigDecimal(1000).pow(2).longValue())); + } + + public void testParsesFileSizeWithGigaByteUnit() { + assertThat(MediaModuleParser.parseFileSize("1GB"), is(new BigDecimal(1000).pow(3).longValue())); + } + + public void testParsesFileSizeWithTeraByteUnit() { + assertThat(MediaModuleParser.parseFileSize("1TB"), is(new BigDecimal(1000).pow(4).longValue())); + } + + public void testParsesFileSizeHandlesSpaces() { + assertThat(MediaModuleParser.parseFileSize(" 1 KB "), is(new BigDecimal(1000).longValue())); + } + + public void testParsesFileSizeHandlesDecimals() { + assertThat(MediaModuleParser.parseFileSize("1.23KB"), is(new BigDecimal(1230).longValue())); + } + + public void testThrowsExceptionOnInvalidFileSize() { + try{ + MediaModuleParser.parseFileSize("reallybig"); + fail("Exception should've been thrown for invalid file size"); + } catch(NumberFormatException ignore) {} + } +} diff --git a/rome-modules/src/test/resources/org/rometools/feed/module/mediarss/filesize-with-unit.xml b/rome-modules/src/test/resources/org/rometools/feed/module/mediarss/filesize-with-unit.xml new file mode 100644 index 0000000..cbed2af --- /dev/null +++ b/rome-modules/src/test/resources/org/rometools/feed/module/mediarss/filesize-with-unit.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file