001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.citation.annotation.output; 031 032import java.io.IOException; 033import java.io.Reader; 034import java.io.StringReader; 035import java.util.Collection; 036import java.util.List; 037 038import org.jbibtex.LaTeXObject; 039import org.jbibtex.LaTeXParser; 040import org.jbibtex.LaTeXPrinter; 041import org.jbibtex.ParseException; 042import org.openimaj.citation.annotation.Reference; 043 044/** 045 * Standard reference formatters. 046 * 047 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 048 */ 049public enum StandardFormatters implements ReferenceFormatter { 050 /** 051 * Format references as BibTeX. 052 * 053 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 054 */ 055 BIBTEX { 056 @Override 057 protected String formatRefs(Iterable<Reference> refs) { 058 final StringBuilder builder = new StringBuilder(); 059 060 for (final Reference r : refs) 061 builder.append(format(r)); 062 063 return builder.toString(); 064 } 065 066 void appendNames(StringBuilder builder, String key, String[] authors) { 067 if (authors == null || authors.length == 0 || (authors.length == 1 && authors[0].length() == 0)) 068 return; 069 070 builder.append(" " + key + " = {"); 071 for (int i = 0; i < authors.length - 1; i++) { 072 builder.append("{" + authors[i] + "} and "); 073 } 074 builder.append("{" + authors[authors.length - 1] + "}"); 075 builder.append("}\n"); 076 } 077 078 @Override 079 public String format(Reference ref) { 080 final StringBuilder builder = new StringBuilder(); 081 082 final String key = ref.hashCode() + ""; 083 builder.append("@" + ref.type() + "{" + key + "\n"); 084 appendNames(builder, "author", ref.author()); 085 086 builder.append(" title = {" + ref.title() + "}\n"); 087 builder.append(" year = {" + ref.year() + "}\n"); 088 089 if (ref.journal().length() > 0) 090 builder.append(" journal = {" + ref.journal() + "}\n"); 091 if (ref.booktitle().length() > 0) 092 builder.append(" booktitle = {" + ref.booktitle() + "}\n"); 093 if (ref.pages().length > 0) { 094 if (ref.pages().length == 1) 095 builder.append(" pages = {" + ref.pages()[0] + "}\n"); 096 else if (ref.pages().length == 2) 097 builder.append(" pages = {" + ref.pages()[0] + "--" + ref.pages()[1] + "}\n"); 098 else { 099 builder.append(" pages = {"); 100 for (int i = 0; i < ref.pages().length - 1; i++) 101 builder.append(ref.pages()[i] + ", "); 102 builder.append(ref.pages()[ref.pages().length - 1] + "}\n"); 103 } 104 } 105 106 if (ref.chapter().length() > 0) 107 builder.append(" chapter = {" + ref.chapter() + "}\n"); 108 if (ref.edition().length() > 0) 109 builder.append(" edition = {" + ref.edition() + "}\n"); 110 if (ref.url().length() > 0) 111 builder.append(" url = {" + ref.url() + "}\n"); 112 if (ref.note().length() > 0) 113 builder.append(" note = {" + ref.note() + "}\n"); 114 115 appendNames(builder, "editor", ref.editor()); 116 117 if (ref.institution().length() > 0) 118 builder.append(" institution = {" + ref.institution() + "}\n"); 119 if (ref.month().length() > 0) 120 builder.append(" month = {" + ref.month() + "}\n"); 121 if (ref.number() != "") 122 builder.append(" number = {" + ref.number() + "}\n"); 123 if (ref.organization().length() > 0) 124 builder.append(" organization = {" + ref.organization() + "}\n"); 125 if (ref.publisher().length() > 0) 126 builder.append(" publisher = {" + ref.publisher() + "}\n"); 127 if (ref.school().length() > 0) 128 builder.append(" school = {" + ref.school() + "}\n"); 129 if (ref.series().length() > 0) 130 builder.append(" series = {" + ref.series() + "}\n"); 131 if (ref.volume() != "") 132 builder.append(" volume = {" + ref.volume() + "}\n"); 133 134 if (ref.customData().length > 1) { 135 for (int i = 0; i < ref.customData().length; i += 2) { 136 builder.append(" " + ref.customData()[i] + " = {" + ref.customData()[i + 1] + "}\n"); 137 } 138 } 139 140 builder.append("}\n"); 141 142 return builder.toString(); 143 } 144 }, 145 /** 146 * Format as a {@link Reference} annotation for inclusion in code 147 * 148 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 149 * 150 */ 151 REFERENCE_ANNOTATION { 152 @Override 153 protected String formatRefs(Iterable<Reference> refs) { 154 final StringBuilder builder = new StringBuilder(); 155 156 for (final Reference r : refs) 157 builder.append(format(r)); 158 159 return builder.toString(); 160 } 161 162 private String formatArray(String[] arr) { 163 final StringBuilder builder = new StringBuilder(); 164 builder.append("{ "); 165 for (int i = 0; i < arr.length - 1; i++) { 166 builder.append(formatString(arr[i]) + ", "); 167 } 168 builder.append(formatString(arr[arr.length - 1]) + " }"); 169 170 return builder.toString(); 171 } 172 173 private String formatString(String str) { 174 return "\"" + str + "\""; 175 } 176 177 @Override 178 public String format(Reference ref) { 179 final StringBuilder builder = new StringBuilder(); 180 181 builder.append("@Reference(\n"); 182 builder.append("\ttype = ReferenceType." + ref.type() + ",\n"); 183 builder.append("\tauthor = " + formatArray(ref.author()) + ",\n"); 184 builder.append("\ttitle = " + formatString(ref.title()) + ",\n"); 185 builder.append("\tyear = " + formatString(ref.year()) + ",\n"); 186 187 if (ref.journal().length() > 0) 188 builder.append("\tjournal = " + formatString(ref.journal()) + ",\n"); 189 if (ref.booktitle().length() > 0) 190 builder.append("\tbooktitle = " + formatString(ref.booktitle()) + ",\n"); 191 if (ref.pages().length > 0) { 192 builder.append("\tpages = " + formatArray(ref.pages()) + ",\n"); 193 } 194 195 if (ref.chapter().length() > 0) 196 builder.append("\tchapter = " + formatString(ref.chapter()) + ",\n"); 197 if (ref.edition().length() > 0) 198 builder.append("\tedition = " + formatString(ref.edition()) + ",\n"); 199 if (ref.url().length() > 0) 200 builder.append("\turl = " + formatString(ref.url()) + ",\n"); 201 if (ref.note().length() > 0) 202 builder.append("\tnote = " + formatString(ref.note()) + ",\n"); 203 if (ref.editor().length > 0) 204 builder.append("\teditor = " + formatArray(ref.editor()) + ",\n"); 205 if (ref.institution().length() > 0) 206 builder.append("\tinstitution = " + formatString(ref.institution()) + ",\n"); 207 if (ref.month().length() > 0) 208 builder.append("\tmonth = " + formatString(ref.month()) + ",\n"); 209 if (ref.number() != "") 210 builder.append("\tnumber = " + formatString(ref.number()) + ",\n"); 211 if (ref.organization().length() > 0) 212 builder.append("\torganization = " + formatString(ref.organization()) + ",\n"); 213 if (ref.publisher().length() > 0) 214 builder.append("\tpublisher = " + formatString(ref.publisher()) + ",\n"); 215 if (ref.school().length() > 0) 216 builder.append("\tschool = " + formatString(ref.school()) + ",\n"); 217 if (ref.series().length() > 0) 218 builder.append("\tseries = " + formatString(ref.series()) + ",\n"); 219 if (ref.volume() != "") 220 builder.append("\tvolume = " + formatString(ref.volume()) + ",\n"); 221 222 if (ref.customData().length > 1) { 223 builder.append("\tcustomData = {\n"); 224 for (int i = 0; i < ref.customData().length; i += 2) { 225 builder.append("\t\t" + formatString(ref.customData()[i]) + ", " 226 + formatString(ref.customData()[i + 1])); 227 if (i < ref.customData().length - 2) 228 builder.append(","); 229 builder.append("\n"); 230 } 231 builder.append("\t}\n"); 232 } 233 234 if (builder.charAt(builder.length() - 2) == ',') { 235 builder.deleteCharAt(builder.length() - 2); 236 } 237 builder.append(")\n"); 238 239 return builder.toString(); 240 } 241 242 }, 243 /** 244 * Format as a pretty string 245 * 246 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 247 */ 248 STRING { 249 @Override 250 protected String formatRefs(Iterable<Reference> refs) { 251 final StringBuilder builder = new StringBuilder(); 252 253 for (final Reference r : refs) 254 builder.append(format(r) + "\n"); 255 256 return builder.toString(); 257 } 258 259 void appendNames(StringBuilder builder, String[] authors) { 260 if (authors == null || authors.length == 0 || (authors.length == 1 && authors[0].length() == 0)) 261 return; 262 263 if (authors.length == 1) { 264 builder.append(formatName(authors[0]) + "."); 265 return; 266 } 267 268 for (int i = 0; i < authors.length - 2; i++) { 269 builder.append(formatName(authors[i]) + ", "); 270 } 271 builder.append(formatName(authors[authors.length - 2]) + " and " + formatName(authors[authors.length - 1]) 272 + ". "); 273 } 274 275 String formatName(String name) { 276 name = format(name); 277 278 if (name.contains(",")) { 279 final String lastName = name.substring(0, name.indexOf(",")); 280 final String[] firstNames = name.substring(name.indexOf(",") + 1).split(" "); 281 282 String formatted = ""; 283 for (String f : firstNames) { 284 f = f.trim(); 285 if (f.length() > 0) 286 formatted += f.charAt(0) + ". "; 287 } 288 289 return formatted + lastName; 290 } else { 291 final String[] parts = name.split(" "); 292 String formatted = ""; 293 294 for (int i = 0; i < parts.length - 1; i++) { 295 formatted += parts[i].charAt(0) + ". "; 296 } 297 298 return formatted + parts[parts.length - 1]; 299 } 300 } 301 302 @Override 303 public String format(Reference ref) { 304 final StringBuilder builder = new StringBuilder(); 305 306 appendNames(builder, ref.author()); 307 308 builder.append(format(ref.title()) + ". "); 309 310 if (ref.journal().length() > 0) 311 builder.append(format(ref.journal()) + ". "); 312 if (ref.booktitle().length() > 0) 313 builder.append(format(ref.booktitle()) + ". "); 314 if (ref.institution().length() > 0) 315 builder.append(format(ref.institution()) + ". "); 316 if (ref.school().length() > 0) 317 builder.append(format(ref.school()) + ". "); 318 if (ref.publisher().length() > 0) 319 builder.append(format(ref.publisher()) + ". "); 320 if (ref.organization().length() > 0) 321 builder.append(format(ref.organization()) + ". "); 322 323 if (ref.pages().length > 0) { 324 if (ref.pages().length == 1) 325 builder.append("p" + ref.pages()[0] + ". "); 326 else if (ref.pages().length == 2) 327 builder.append("pp" + ref.pages()[0] + "-" + ref.pages()[1] + ". "); 328 else { 329 builder.append("pp"); 330 for (int i = 0; i < ref.pages().length - 1; i++) 331 builder.append(ref.pages()[i] + ", "); 332 builder.append(ref.pages()[ref.pages().length - 1] + ". "); 333 } 334 } 335 336 if (ref.month().length() > 0) 337 builder.append(format(ref.month()) + ", "); 338 builder.append(format(ref.year()) + ". "); 339 340 if (ref.url().length() > 0) 341 builder.append(format(ref.url())); 342 343 return builder.toString(); 344 } 345 }, 346 /** 347 * Format as an HTML fragment 348 * 349 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 350 */ 351 HTML { 352 @Override 353 protected String formatRefs(Iterable<Reference> refs) { 354 final StringBuilder builder = new StringBuilder(); 355 356 for (final Reference r : refs) { 357 builder.append("<p class=\"ref\">"); 358 builder.append(format(r)); 359 builder.append("</p>\n"); 360 } 361 362 return builder.toString(); 363 } 364 365 void appendNames(StringBuilder builder, String[] authors) { 366 if (authors == null || authors.length == 0 || (authors.length == 1 && authors[0].length() == 0)) 367 return; 368 369 if (authors.length == 1) { 370 builder.append(formatName(authors[0]) + ". "); 371 return; 372 } 373 374 for (int i = 0; i < authors.length - 2; i++) { 375 builder.append(formatName(authors[i]) + ", "); 376 } 377 builder.append(formatName(authors[authors.length - 2]) + " and " + formatName(authors[authors.length - 1]) 378 + ". "); 379 } 380 381 String formatName(String name) { 382 name = format(name); 383 384 if (name.contains(",")) { 385 final String lastName = name.substring(0, name.indexOf(",")); 386 final String[] firstNames = name.substring(name.indexOf(",") + 1).split(" "); 387 388 String formatted = ""; 389 for (String f : firstNames) { 390 f = f.trim(); 391 if (f.length() > 0) 392 formatted += f.charAt(0) + ". "; 393 } 394 395 return formatted + lastName; 396 } else { 397 final String[] parts = name.split(" "); 398 String formatted = ""; 399 400 for (int i = 0; i < parts.length - 1; i++) { 401 formatted += parts[i].charAt(0) + ". "; 402 } 403 404 return formatted + parts[parts.length - 1]; 405 } 406 } 407 408 @Override 409 public String format(Reference ref) { 410 final StringBuilder builder = new StringBuilder(); 411 412 builder.append("<span class='authors'>"); 413 appendNames(builder, ref.author()); 414 builder.append("</span>"); 415 416 builder.append("<span class='title'>"); 417 builder.append(format(ref.title()) + ". "); 418 builder.append("</span>"); 419 420 if (ref.journal().length() > 0) 421 builder.append("<span class='journal'>" + format(ref.journal()) + ". </span>"); 422 if (ref.booktitle().length() > 0) 423 builder.append("<span class='booktitle'>" + format(ref.booktitle()) + ". </span>"); 424 if (ref.institution().length() > 0) 425 builder.append("<span class='institution'>" + format(ref.institution()) + ". </span>"); 426 if (ref.school().length() > 0) 427 builder.append("<span class='school'>" + format(ref.school()) + ". </span>"); 428 if (ref.publisher().length() > 0) 429 builder.append("<span class='publisher'>" + format(ref.publisher()) + ". </span>"); 430 if (ref.organization().length() > 0) 431 builder.append("<span class='organization'>" + format(ref.organization()) + ". </span>"); 432 433 if (ref.pages().length > 0) { 434 if (ref.pages().length == 1) 435 builder.append("<span class='pages'>" + "p" + ref.pages()[0] + ". </span>"); 436 else if (ref.pages().length == 2) 437 builder.append("<span class='pages'>" + "pp" + ref.pages()[0] + "-" + ref.pages()[1] + ". </span>"); 438 else { 439 builder.append("<span class='pages'>" + "pp"); 440 for (int i = 0; i < ref.pages().length - 1; i++) 441 builder.append(ref.pages()[i] + ", "); 442 builder.append(ref.pages()[ref.pages().length - 1] + ". </span>"); 443 } 444 } 445 446 if (ref.month().length() > 0) 447 builder.append("<span class='month'>" + format(ref.month()) + ", </span>"); 448 builder.append("<span class='year'>" + format(ref.year()) + ". </span>"); 449 450 if (ref.url().length() > 0) 451 builder.append("<a class='url' href='" + format(ref.url()) + "'>" + format(ref.url()) + "</a>"); 452 453 return builder.toString(); 454 } 455 }; 456 457 protected abstract String formatRefs(Iterable<Reference> refs); 458 459 @Override 460 public abstract String format(Reference ref); 461 462 @Override 463 public String format(Collection<Reference> refs) { 464 return formatRefs(refs); 465 } 466 467 static List<LaTeXObject> parseLaTeX(String string) throws IOException, ParseException { 468 final Reader reader = new StringReader(string); 469 470 try { 471 final LaTeXParser parser = new LaTeXParser(); 472 473 return parser.parse(reader); 474 } finally { 475 reader.close(); 476 } 477 } 478 479 static String printLaTeX(List<LaTeXObject> objects) { 480 final LaTeXPrinter printer = new LaTeXPrinter(); 481 482 return printer.print(objects); 483 } 484 485 static String format(String latex) { 486 try { 487 return printLaTeX(parseLaTeX(latex)); 488 } catch (final Exception e) { 489 return latex; 490 } 491 } 492}