Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding log4j support (with a copy & pasted class from my project_eule…

…r github project....I should probably break that log helper out to some separate support jar)

Adding rough implementation of the TabSeperatedArticleParser and a little bit of test coverage.

Implemented expected/required fields as assertions in the Article object

Added support for the concept of "header row" in the ArticleParser
  • Loading branch information...
commit 6b0c8a1b25de83ff7e1329e8cbe8635ebfed7f7a 1 parent 4eddf00
@tvaughan77 authored
View
4 mag_art_dl/pom.xml
@@ -18,6 +18,10 @@
<artifactId>scala-library</artifactId>
</dependency>
<dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
View
26 mag_art_dl/src/main/resources/log4j.properties
@@ -0,0 +1,26 @@
+log4j.debug=true
+log4j.rootLogger=WARN, file, debug, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%-5p [%5.15t] %d [%.30c] %m%n
+
+log4j.logger.vaughan=DEBUG
+
+log4j.appender.file=org.apache.log4j.RollingFileAppender
+log4j.appender.file.threshold=INFO
+log4j.appender.file.append=false
+log4j.appender.file.file=target/output.log
+log4j.appender.file.MaxFileSize=1024KB
+log4j.appender.file.MaxBackupIndex=3
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%-5p %d [%c{3}] %m%n
+
+log4j.appender.debug=org.apache.log4j.RollingFileAppender
+log4j.appender.debug.threshold=DEBUG
+log4j.appender.debug.append=false
+log4j.appender.debug.file=target/debug.log
+log4j.appender.debug.MaxFileSize=10240KB
+log4j.appender.debug.MaxBackupIndex=1
+log4j.appender.debug.layout=org.apache.log4j.PatternLayout
+log4j.appender.debug.layout.ConversionPattern=%-5p %d [%c{3}] %m%n
View
39 mag_art_dl/src/main/scala/vaughan/LogHelper.scala
@@ -0,0 +1,39 @@
+package vaughan
+
+import org.apache.log4j.Logger
+import org.apache.log4j.Priority
+import java.util.Locale
+
+/**
+ * <p>From http://www.uncarved.com/blog/LogHelper.mrk</p>
+ *
+ * <p>LogHelper is a trait you can mix in to provide easy log4j logging
+ * for your scala classes. </p>
+ **/
+trait LogHelper {
+ val loggerName = this.getClass.getName
+ lazy val logger = Logger.getLogger(loggerName)
+ lazy val locale = Locale.getDefault
+
+ def debug(message: String, args: Any*) {
+ log(Priority.DEBUG, message, args:_*)
+ }
+
+ def info(message: String, args: Any*) {
+ log(Priority.INFO, message, args:_*)
+ }
+
+ def warn(message: String, args: Any*) {
+ log(Priority.WARN, message, args:_*)
+ }
+
+ def error(message: String, args: Any*) {
+ log(Priority.ERROR, message, args:_*)
+ }
+
+ private def log(priority: Priority, message: String, args: Any*) {
+ if(logger.isEnabledFor(priority)) {
+ logger.log(priority, message.format(args:_*))
+ }
+ }
+}
View
6 mag_art_dl/src/main/scala/vaughan/model/Article.scala
@@ -21,6 +21,12 @@ class Article(val publication: String,
val notes: String,
val categories: List[String]) {
+ require(publication != null && !publication.isEmpty)
+ require(edition!= null)
+ require(page > 0)
+ require(title != null && !title.isEmpty)
+ require(categories != null && categories.size > 0)
+
/**
* <p>Convenience constructor - the description and notes probably aren't likely to be filled in very often, but
* shorthanding the edition date string probably is.</p>
View
42 mag_art_dl/src/main/scala/vaughan/parser/TabSeperatedArticleParser.scala
@@ -1,6 +1,7 @@
package vaughan.parser
import vaughan.model.Article
+import vaughan.LogHelper
import scala.io.Source
/**
@@ -8,27 +9,56 @@ import scala.io.Source
* be parsed into an {@code Article} object. It is further assumed that each line from the source contains a complete
* Article object. Back-to-back tabs in the input source implies an empty value for the field.</p>
*
- * TODO: what's a good scala-like treatment for "has header row"?
- *
* @author tom.vaughan
*/
-object TabSeperatedArticleParser extends ArticleParser {
+class TabSeperatedArticleParser(val hasHeaderRow: Boolean) extends ArticleParser with LogHelper {
+
+ def this() = this(false)
/**
* {@inheritDoc}
*/
def parseSource(source: Source): List[Article] = {
+ val lines =
+ if(hasHeaderRow)
+ source.getLines().toList.tail
+ else
+ source.getLines().toList
+
+ val articles = scala.collection.mutable.Set.empty[Article]
+ for(line <- lines)
+ articles += TabSeperatedArticleParser.parseLine(line)
- List(Article.mockArticle1, Article.mockArticle2)
+ articles.toList
}
+}
+
+
+object TabSeperatedArticleParser extends LogHelper {
- def parseLine(line: String): Article = {
+ /**
+ * @param line a single line containing exactly 7 tokens of tab-separated information in it, with this spec:
+ * <ol>
+ * <li>Name of the publication</li>
+ * <li>The edition of the publication, in date format like "Mar 2011" or "Aug 2009"</li>
+ * <li>The first page of the article, parseable as an integer</li>
+ * <li>The title of the article</li>
+ * <li>An optional description of the article.</li>
+ * <li>An optional string containing notes about the article</li>
+ * <li>A comma separated list of categories (meta-data) describing the article</li>
+ * </ol>
+ */
+ private def parseLine(line: String): Article = {
val tokens = line.split('\t')
- require(7 == tokens.size)
+ debug("parsing input line '%s'", line)
+ require(7 == tokens.size, {error("Input line only had %d tokens", tokens.size)})
+
val edition = Article.dFormat.parse(tokens(1))
val page = tokens(2).toInt
val categories = tokens(6).split(",").toList
+ debug("categories = %s", categories.mkString)
+
new Article(tokens(0), edition, page, tokens(3), tokens(4), tokens(5), categories)
}
}
View
4 mag_art_dl/src/test/resources/vaughan/parser/one_article.tdf
@@ -1,2 +1,2 @@
-Publication Edition Page Title Description Notes Categories
-Sailing World March 2011 12 Alpha Title Some Description of the article My notes about the article Electronics
+Publication Edition Page Title Description Notes Categories
+Sailing World March 2011 12 Alpha Title Some Description of the article My notes about the article Electronics
View
6 mag_art_dl/src/test/scala/vaughan/model/ArticleSuite.scala
@@ -37,4 +37,10 @@ class ArticleSuite extends FunSuite {
assertEquals(3, myArticle.categories.size)
assertEquals(format.parse("2011-07-01"), myArticle.edition)
}
+
+ test("Not providing a publication is an exception") {
+ intercept[IllegalArgumentException] {
+ new Article("", "Jul 2011", 1, "Title", List("foo"))
+ }
+ }
}
View
5 mag_art_dl/src/test/scala/vaughan/parser/TabSeperatedArticleParserSuite.scala
@@ -10,8 +10,9 @@ import scala.io.Source
@RunWith(classOf[JUnitRunner])
class TabSeperatedArticleParserSuite extends FunSuite {
- test("Reading from a test source produces 2 articles") {
+ test("Reading from a test source file with a header row produces 1 articles") {
val source = Source.fromInputStream(getClass.getResourceAsStream("one_article.tdf"))
- assertEquals(2, TabSeperatedArticleParser.parseSource(source).size)
+ val parser = new TabSeperatedArticleParser(true)
+ assertEquals(1, parser.parseSource(source).size)
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.