View Javadoc
1   /**
2    * Copyright 2004-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.common.aws.s3.monitor;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.text.SimpleDateFormat;
21  import java.util.ArrayList;
22  import java.util.Collections;
23  import java.util.Date;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.TreeMap;
27  
28  import org.apache.commons.io.FileUtils;
29  import org.kuali.common.aws.s3.pojo.AccountDeltaSummary;
30  import org.kuali.common.aws.s3.pojo.BucketDeltaLine;
31  import org.kuali.common.aws.s3.pojo.BucketDeltaSummary;
32  import org.kuali.common.aws.s3.pojo.BucketSummaryLine;
33  import org.kuali.common.aws.s3.pojo.BucketSummaryLineComparator;
34  import org.kuali.common.util.FormatUtils;
35  
36  public class DeltaUtils {
37  	SimpleDateFormat shortDateFormatter = new SimpleDateFormat("yyyy-MM-dd");
38  
39  	private static DeltaUtils instance;
40  
41  	public static synchronized DeltaUtils getInstance() {
42  		if (instance == null) {
43  			instance = new DeltaUtils();
44  		}
45  		return instance;
46  	}
47  
48  	protected DeltaUtils() {
49  		super();
50  	}
51  
52  	public AccountDeltaSummary getAccountDeltaSummary(File csv) {
53  
54  		List<String> lines = getLines(csv);
55  		List<BucketSummaryLine> summaryLines = getBucketSummaryLines(lines);
56  		List<String> buckets = getBucketNames(summaryLines);
57  		List<BucketDeltaSummary> bucketDeltaSummaries = new ArrayList<BucketDeltaSummary>();
58  
59  		for (String bucket : buckets) {
60  			List<BucketSummaryLine> matchingLines = getMatchingSummaryLines(bucket, summaryLines);
61  			BucketDeltaSummary bds = getBucketDeltaSummary(matchingLines);
62  			List<BucketDeltaLine> deltaLines = getBucketDeltaLines(matchingLines);
63  			bds.setBucket(bucket);
64  			bds.setDeltaLines(deltaLines);
65  			bucketDeltaSummaries.add(bds);
66  		}
67  
68  		AccountDeltaSummary ads = new AccountDeltaSummary();
69  		ads.setBucketDeltaSummaries(bucketDeltaSummaries);
70  		return ads;
71  	}
72  
73  	public BucketDeltaSummary getBucketDeltaSummary(List<BucketSummaryLine> summaryLines) {
74  		// If we don't have at least 2 lines we can't calculate any delta's
75  		if (summaryLines.size() < 2) {
76  			return new BucketDeltaSummary();
77  		}
78  
79  		BucketSummaryLine first = summaryLines.get(0);
80  		BucketSummaryLine last = summaryLines.get(summaryLines.size() - 1);
81  
82  		Date startDate = first.getDate();
83  		Date endDate = last.getDate();
84  		long interval = endDate.getTime() - startDate.getTime();
85  		long fileDelta = last.getFiles() - first.getFiles();
86  		long byteDelta = last.getBytes() - first.getBytes();
87  
88  		BucketDeltaSummary deltaSummary = new BucketDeltaSummary();
89  		deltaSummary.setByteDelta(byteDelta);
90  		deltaSummary.setInterval(interval);
91  		deltaSummary.setStartDate(startDate);
92  		deltaSummary.setEndDate(endDate);
93  		deltaSummary.setFileDelta(fileDelta);
94  		return deltaSummary;
95  	}
96  
97  	public String toString(AccountDeltaSummary summary) {
98  		List<String[]> rows = new ArrayList<String[]>();
99  		for (BucketDeltaSummary bds : summary.getBucketDeltaSummaries()) {
100 			rows.addAll(getRows(bds.getBucket(), bds.getDeltaLines()));
101 			String files = FormatUtils.getCount(bds.getFileDelta());
102 			String bytes = FormatUtils.getSize(bds.getByteDelta());
103 			String start = shortDateFormatter.format(bds.getStartDate());
104 			String end = shortDateFormatter.format(bds.getEndDate());
105 			String interval = FormatUtils.getTime(bds.getInterval());
106 			rows.add(new String[] { "", "", "", "", "", "" });
107 			rows.add(new String[] { "totals", files, bytes, start, end, interval });
108 			rows.add(getPerDayRow(bds));
109 			rows.add(new String[] { "", "", "", "", "", "" });
110 			rows.add(new String[] { "", "", "", "", "", "" });
111 		}
112 		List<String> columns = new ArrayList<String>();
113 		columns.add("bucket");
114 		columns.add("files");
115 		columns.add("size");
116 		columns.add("start");
117 		columns.add("end");
118 		columns.add("interval");
119 		return S3Utils.getInstance().toString(columns, rows);
120 	}
121 
122 	protected String[] getPerDayRow(BucketDeltaSummary bds) {
123 		String perDay = "per day";
124 		double days = bds.getInterval() / FormatUtils.DAY;
125 		String files = FormatUtils.getCount((long) (bds.getFileDelta() / days));
126 		long byteDelta = bds.getByteDelta();
127 		long bytesPerDay = (long) (byteDelta / days);
128 		String bytes = FormatUtils.getSize(bytesPerDay);
129 		return new String[] { perDay, files, bytes, "", "", "" };
130 	}
131 
132 	public List<String[]> getRows(String bucket, List<BucketDeltaLine> deltaLines) {
133 		List<String[]> rows = new ArrayList<String[]>();
134 		for (BucketDeltaLine deltaLine : deltaLines) {
135 			String files = FormatUtils.getCount(deltaLine.getFileDelta());
136 			String size = FormatUtils.getSize(deltaLine.getByteDelta());
137 			String start = shortDateFormatter.format(deltaLine.getStartDate());
138 			String end = shortDateFormatter.format(deltaLine.getEndDate());
139 			String interval = FormatUtils.getTime(deltaLine.getInterval());
140 			String[] row = new String[] { bucket, files, size, start, end, interval };
141 			rows.add(row);
142 		}
143 		return rows;
144 	}
145 
146 	public List<String> getLines(File file) {
147 		try {
148 			return FileUtils.readLines(file);
149 		} catch (IOException e) {
150 			throw new IllegalStateException("Can't read lines from " + getCanonicalPath(file), e);
151 		}
152 	}
153 
154 	public String getCanonicalPath(File file) {
155 		try {
156 			return file.getCanonicalPath();
157 		} catch (IOException e) {
158 			throw new IllegalArgumentException("Unable to determine canonical path for " + file, e);
159 		}
160 	}
161 
162 	public List<BucketSummaryLine> getBucketSummaryLines(List<String> lines) {
163 		List<BucketSummaryLine> summaryLines = new ArrayList<BucketSummaryLine>();
164 		// Start at 1 instead of zero in order to skip the first line since it is just the column headers
165 		for (int i = 1; i < lines.size(); i++) {
166 			String line = lines.get(i);
167 			String[] tokens = line.split(",");
168 			String bucket = tokens[0];
169 			Long files = new Long(tokens[1]);
170 			Long bytes = new Long(tokens[2]);
171 			Date date = FormatUtils.parseDate(tokens[3]);
172 			BucketSummaryLine bsl = new BucketSummaryLine();
173 			bsl.setBucket(bucket);
174 			bsl.setFiles(files);
175 			bsl.setBytes(bytes);
176 			bsl.setDate(date);
177 			summaryLines.add(bsl);
178 		}
179 		return summaryLines;
180 	}
181 
182 	public List<String> getBucketNames(List<BucketSummaryLine> summaryLines) {
183 		Map<String, String> map = new TreeMap<String, String>();
184 		for (BucketSummaryLine bsl : summaryLines) {
185 			map.put(bsl.getBucket(), bsl.getBucket());
186 		}
187 		return new ArrayList<String>(map.keySet());
188 
189 	}
190 
191 	public List<BucketDeltaLine> getBucketDeltaLines(List<BucketSummaryLine> summaryLines) {
192 		List<BucketDeltaLine> bdls = new ArrayList<BucketDeltaLine>();
193 		for (int i = 0; i < summaryLines.size() - 1; i++) {
194 			BucketSummaryLine current = summaryLines.get(i);
195 			BucketSummaryLine next = summaryLines.get(i + 1);
196 			long fileDelta = next.getFiles() - current.getFiles();
197 			long byteDelta = next.getBytes() - current.getBytes();
198 			Date startDate = current.getDate();
199 			Date endDate = next.getDate();
200 			long interval = endDate.getTime() - startDate.getTime();
201 			BucketDeltaLine bdl = new BucketDeltaLine();
202 			bdl.setFileDelta(fileDelta);
203 			bdl.setByteDelta(byteDelta);
204 			bdl.setStartDate(startDate);
205 			bdl.setEndDate(endDate);
206 			bdl.setInterval(interval);
207 			bdls.add(bdl);
208 		}
209 		return bdls;
210 	}
211 
212 	public List<BucketSummaryLine> getMatchingSummaryLines(String bucket, List<BucketSummaryLine> summaryLines) {
213 		Collections.sort(summaryLines, new BucketSummaryLineComparator());
214 		List<BucketSummaryLine> matchingLines = new ArrayList<BucketSummaryLine>();
215 		for (BucketSummaryLine bsl : summaryLines) {
216 			if (bsl.getBucket().equals(bucket)) {
217 				matchingLines.add(bsl);
218 			}
219 		}
220 		return matchingLines;
221 	}
222 
223 }