/* * [ProviderBase.java] * * Summary: Base class for all poster providers. * * Copyright: (c) 2008-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.1 2008-09-27 */ package com.mindprod.poster; import com.mindprod.common18.ST; import com.mindprod.fastcat.FastCat; import com.mindprod.htmlmacros.support.BuildImage; import com.mindprod.hunkio.HunkIO; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Base class for all poster providers. * * @author Roedy Green, Canadian Mind Products * @version 1.1 2008-09-27 * @since 2008 */ abstract class ProviderBase { /** * true if should check if already done */ static final boolean CHECK_IF_ALREADY_DONE = true; /** * true if debugging, display extra output */ static final boolean DEBUGGING = false; /** * true if testing, don't actually change any files or check if done before */ static final boolean TESTING = false; /** * find place to patch image background colour */ private static final Pattern BACKGROUND_FOR_PATCH_COLOR = Pattern.compile( "div.titlehome\\s*\\{\\s*+background\\-color:\\s*(#\\p{XDigit}{6});" ); /** * find place to patch image foreground colour */ private static final Pattern PATCH_FOREGROUND_COLOR = Pattern.compile( "div.titlehome\\s+h1\\s*\\{\\s*color:\\s*(#\\p{XDigit}{6});" ); /** * a description of the image */ final String extraDescription/* "René Magritte’s The Last Cry" */; /** * name of local large jpg with .jpg or .png extension or directory */ final String bareImageName/* "maldives.jpg" */; /** * a few words to title the poster thumbnail */ final String title; /** * used to ensure a colour has the format #rrggbb */ @SuppressWarnings( { "FieldCanBeLocal" } ) private final Pattern LEGAL_COLOUR_PATTERN = Pattern.compile( "#[\\p{XDigit}]{6}" ); /** * background colour to match the image, #rrggbb with lead # */ private final String background; /** * foreground colour to match the image, #rrggbb with lead # */ private final String foreground; /** * text of index.html */ String homePage; /** * height of the local image in px */ int localImageHeight/* 266 px */; /** * width of the local image in px */ int localImageWidth/* 400 px */; /** * home.css, the aux style sheet to let us control home page colours. */ private File homeCssFile; /** * index.htm */ private File indexHtmlFile; /** * text of home.css */ private String stylesheet; /** * abstract constructor to describe a new Poster. * * @param bareImageName name of local image ending in .jpg .png or gif * @param title short title of the picture * @param extraDescription what is in the picture, a longer description of the picture. * @param background #rrggbb hex background * @param foreground #rrggbb hex foreground */ ProviderBase( String bareImageName, final String title, final String extraDescription, String background, String foreground ) { // forgive extra lead #. Work internally with lead # background = '#' + ST.trimLeading( background, '#' ); if ( LEGAL_COLOUR_PATTERN.matcher( background ).matches() ) { this.background = background; } else { throw new IllegalArgumentException( "Invalid background colour " + background ); } foreground = '#' + ST.trimLeading( foreground, '#' ); if ( LEGAL_COLOUR_PATTERN.matcher( foreground ).matches() ) { this.foreground = foreground; } else { throw new IllegalArgumentException( "Invalid foreground colour " + foreground ); } this.title = title; if ( !( bareImageName.endsWith( ".jpg" ) || bareImageName.endsWith( ".png" ) || bareImageName.endsWith( ".gif" ) ) ) { bareImageName += ".jpg"; } this.bareImageName = bareImageName; this.extraDescription = extraDescription; } /** * save data to a file in one big chunk with safety temp rename to avoid data corruption if we fail to complete * the write.. * * @param fileBeingProcessed file to save data to * @param contents contents of file. * * @throws IOException if problem saving the file */ static void saveOneFile( File fileBeingProcessed, String contents ) throws IOException { final File tempFile = HunkIO.createTempFile( "temp_", ".tmp", fileBeingProcessed ); final FileWriter emit = new FileWriter( tempFile ); emit.write( contents ); emit.close(); HunkIO.deleteAndRename( tempFile, fileBeingProcessed ); } /** * get rid of any old local images, keep current one. */ @SuppressWarnings( { "ResultOfMethodCallIgnored" } ) void deleteOldLocalImages() { // look in E:\mindprod\image\home File dir = new File( "E:/mindprod/image", providerName() ); String[] files = dir.list(); for ( String file : files ) { File old = new File( dir, file ); if ( !old.getName().startsWith( bareImageName ) ) { old.delete(); } } } /** * get the local image size. Stores results in localImageWidth and localImageSize. */ void getLocalImageSize() { final int[] dimensions = BuildImage.getProjectImageDimensions( providerName() + "/" + bareImageName ); localImageWidth = dimensions[ 0 ]; localImageHeight = dimensions[ 1 ]; if ( localImageWidth == 0 ) { throw new IllegalArgumentException( "missing Image file " + bareImageName + " or malformed size " + localImageWidth + " x " + localImageHeight ); } } /** * internal provider name, also dir where the local image is stored on hard disk, without lead E:/mindprod/image * * @return e.g. artcom or allposterscom */ abstract String providerName(); /** * read all poster files files into RAM * * @throws java.io.IOException if can't access one of the poster html files. */ void read() throws IOException { indexHtmlFile = new File( "E:/mindprod/index.html" ); homeCssFile = new File( "E:/mindprod/home.css" ); homePage = HunkIO.readEntireFile( indexHtmlFile ); stylesheet = HunkIO.readEntireFile( homeCssFile ); } /** * replace background and foreground colours on titlehome style. */ void replaceColoursOnStylesheet() { // patch background colour // div.titlehome{ // background-color: #a0bcd4 final Matcher mb = BACKGROUND_FOR_PATCH_COLOR.matcher( stylesheet ); final int backgroundOffset; if ( mb.find() ) { backgroundOffset = mb.start( 1 ); } else { throw new IllegalArgumentException( "can't find background-color: in home.css" ); } // patch foreground colour // div.titlehome h1{ // color: #f1f4ed; final Matcher mf = PATCH_FOREGROUND_COLOR.matcher( stylesheet.substring( backgroundOffset ) ); final int foregroundOffset; if ( mf.find() ) { // get absolute offset inside stylesheet foregroundOffset = mf.start( 1 ) + backgroundOffset; } else { throw new IllegalArgumentException( "can't find foreground color, div.titlehome h1 { color:, in home.css" ); } /// should stay exactly the same length. final int repLen = "#rrggbb".length(); final FastCat sb = new FastCat( 5 ); sb.append( stylesheet.substring( 0, backgroundOffset ) ); sb.append( background ); sb.append( stylesheet.substring( backgroundOffset + repLen, foregroundOffset ) ); sb.append( foreground ); sb.append( stylesheet.substring( foregroundOffset + repLen ) ); stylesheet = sb.toString(); } /** * replace the reference to the local image on the home page */ abstract void replaceLocalImageOnHomePage(); /** * save all changes in RAM to data files. * * @throws IOException if problem writing files. */ void save() throws IOException { saveOneFile( indexHtmlFile, homePage ); saveOneFile( homeCssFile, stylesheet ); } }