001 package hirondelle.web4jtools.metrics.images; 002 003 import static hirondelle.web4j.util.Consts.NOT_FOUND; 004 import hirondelle.web4j.action.ResponsePage; 005 import hirondelle.web4j.request.RequestParameter; 006 import hirondelle.web4j.request.RequestParser; 007 import hirondelle.web4j.util.Util; 008 import hirondelle.web4jtools.metrics.base.FileInfo; 009 import hirondelle.web4jtools.metrics.base.MetricsAction; 010 011 import java.util.ArrayList; 012 import java.util.Collections; 013 import java.util.Comparator; 014 import java.util.List; 015 ; 016 017 /** 018 * List all images in the target project, along with all references to each image occurring in 019 * markup files. 020 * Any image having 0 references are candidates for removal from the project. 021 */ 022 public class ImageReferencesAction extends MetricsAction { 023 024 /** Full constructor. */ 025 public ImageReferencesAction(RequestParser aRequestParser){ 026 super(FORWARD, aRequestParser); 027 } 028 029 /** The column of the listing to sort on. See the <tt>sortLinks.tag</tt> file. */ 030 public static final RequestParameter SORT_ON = RequestParameter.withRegexCheck("SortOn", "(Name|NumReferences|Bytes)"); 031 /** Ascending or descending order. See the <tt>sortLinks.tag</tt> file. */ 032 public static final RequestParameter ORDER = RequestParameter.withRegexCheck("Order", "(ASC|DESC)"); 033 034 /** 035 * Show a sortable listing of images and the files that reference them. 036 * The default sort is by the number of references. 037 */ 038 @Override protected void calculateMetric() { 039 List<ImageReference> imgRefs = new ArrayList<ImageReference>(); 040 List<FileInfo> imageFiles = filterImageFiles(); 041 List<FileInfo> markupFiles = filterMarkupFiles(); 042 initializeImageReferences(imgRefs, imageFiles); 043 044 for(FileInfo markupFile : markupFiles){ 045 String markupFileContent = markupFile.getContent(); 046 for (FileInfo imageFile : imageFiles) { 047 if( hasImageReference(markupFileContent, imageFile)){ 048 addImageReference(markupFile, imageFile, imgRefs); 049 } 050 } 051 } 052 sort(imgRefs); 053 addToRequest("imgReferences", imgRefs); 054 } 055 056 057 // PRIVATE // 058 private static final ResponsePage FORWARD = new ResponsePage("Images and Their References", "view.jsp", ImageReferencesAction.class); 059 060 private List<FileInfo> filterImageFiles() { 061 List<FileInfo> result = new ArrayList<FileInfo>(); 062 for(FileInfo file : fFileList){ 063 if ( file.isImageFile() ) { 064 result.add(file); 065 } 066 } 067 return result; 068 } 069 070 private List<FileInfo> filterMarkupFiles() { 071 List<FileInfo> result = new ArrayList<FileInfo>(); 072 for(FileInfo file : fFileList){ 073 if ( file.isMarkupFile() ) { 074 result.add(file); 075 } 076 } 077 return result; 078 } 079 080 private void initializeImageReferences(List<ImageReference> aImgRefs, List<FileInfo> aImageFiles){ 081 for(FileInfo imageFile : aImageFiles) { 082 aImgRefs.add(new ImageReference(imageFile)); 083 } 084 } 085 086 /** 087 * This check is a bit simplistic, since it does not use path information at all. 088 * It only checks if the file contains the simple image file name, anywhere in its 089 * body, without using the full path of the image file. 090 * 091 * <P>This style at least allows for referencing image files in many different ways. 092 */ 093 private boolean hasImageReference(String aMarkupFileContent, FileInfo aImageFile){ 094 return aMarkupFileContent.indexOf(aImageFile.getSimpleName().getRawString()) != NOT_FOUND; 095 } 096 097 private void addImageReference(FileInfo aMarkupFile, FileInfo aImageFile, List<ImageReference> aImgRefs) { 098 ImageReference imageRef = null; 099 for (ImageReference item : aImgRefs){ 100 if (item.getFileInfo().equals(aImageFile)) { 101 imageRef = item; 102 break; 103 } 104 } 105 if ( imageRef == null ) { 106 throw new AssertionError("Cannot find image file as expected."); 107 } 108 imageRef.addReferenceFrom(aMarkupFile); 109 } 110 111 private void sort(List<ImageReference> aImgRefs) { 112 String sortOn = getParamUnsafe(SORT_ON); 113 String order = getParamUnsafe(ORDER); 114 Collections.sort(aImgRefs, getComparator(sortOn)); 115 if( "DESC".equals(order) || ! Util.textHasContent(order)) { 116 Collections.reverse(aImgRefs); 117 } 118 } 119 120 private Comparator<ImageReference> getComparator(String aSortOn){ 121 Comparator<ImageReference> result = null; 122 if( "Name".equals(aSortOn) ) { 123 result = new Comparator<ImageReference>() { 124 public int compare(ImageReference aThis, ImageReference aThat) { 125 String thisName = aThis.getFileInfo().getSimpleName().getRawString(); 126 String thatName = aThat.getFileInfo().getSimpleName().getRawString(); 127 return thisName.compareTo(thatName); 128 }; 129 }; 130 } 131 if( "Bytes".equals(aSortOn) ) { 132 result = new Comparator<ImageReference>() { 133 public int compare(ImageReference aThis, ImageReference aThat) { 134 Long thisSize = aThis.getFileInfo().getSize(); 135 Long thatSize = aThat.getFileInfo().getSize(); 136 return thisSize.compareTo(thatSize); 137 }; 138 }; 139 } 140 //default sorting by num references 141 else if ( "NumReferences".equals(aSortOn) || ! Util.textHasContent(aSortOn) ) { 142 result = new Comparator<ImageReference>() { 143 public int compare(ImageReference aThis, ImageReference aThat) { 144 return aThis.getNumReferences().compareTo(aThat.getNumReferences()); 145 }; 146 }; 147 } 148 else { 149 throw new AssertionError("Unknown sort column : " + Util.quote(aSortOn)); 150 } 151 return result; 152 } 153 }