/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.ui.swt.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.riena.core.singleton.SessionSingletonProvider;
import org.eclipse.riena.core.singleton.SingletonProvider;
import org.eclipse.riena.core.util.ObjectCounter;
import org.eclipse.riena.internal.ui.swt.console.UIControlsStatisticCommandProvider;
/**
* Statistic Counter of {@link Control}s created by {@link UIControlsFactory}.
* Used by {@link UIControlsStatisticCommandProvider} to get statistics.
*
* @since 3.0
*/
public class UIControlsCounter {
private final static String STAR = "*"; //$NON-NLS-1$
private static final String HEADER = " Control Usage Statistics "; //$NON-NLS-1$
private static final int NOS = 10;
private static final SingletonProvider<UIControlsCounter> UICC = new SessionSingletonProvider<UIControlsCounter>(
UIControlsCounter.class);
private final ObjectCounter<Class<?>> live = new ObjectCounter<Class<?>>();
private final ObjectCounter<Class<?>> total = new ObjectCounter<Class<?>>();
private final DisposeListener disposeListener = new LiveDisposeListener();
public static final String CONTROL_STATS_PROPERTY_NAME = "riena.control.stats"; //$NON-NLS-1$
private static final boolean CONTROL_STATS_REQUESTED = Boolean.getBoolean(CONTROL_STATS_PROPERTY_NAME);
/**
* Asks whether control counting statistics are requested or not.
*
* @return {@code true} for statistics should be activated; otherwise
* {@code false}
*/
public static boolean isRequested() {
return CONTROL_STATS_REQUESTED;
}
/**
* @return - the Singleton instance of {@link UIControlsCounter}
*/
public static UIControlsCounter getInstance() {
return UICC.getInstance();
}
/**
* Register the given control for statistic reasons
*
* @param control
* - the control to register
*/
public void registerConstruction(final Object control) {
if (isRequested()) {
total.incrementAndGetCount(control.getClass());
live.incrementAndGetCount(control.getClass());
if (control instanceof Widget) {
((Widget) control).addDisposeListener(disposeListener);
}
}
}
/**
*
*/
private final class LiveDisposeListener implements DisposeListener {
public void widgetDisposed(final DisposeEvent e) {
live.decrementAndGetCount(e.widget.getClass());
}
}
/**
* Get a formatted String of Control usage statistics
*
* @return - the statistic in String format
*/
public String getControlUsageStatistics() {
final StringBuilder strb = new StringBuilder();
appendNTimes(STAR, NOS, strb);
strb.append(HEADER);
appendNTimes(STAR, NOS, strb);
newLine(strb);
strb.append(" Live" + DELIMITER); //$NON-NLS-1$
strb.append("Total" + DELIMITER); //$NON-NLS-1$
strb.append("Type"); //$NON-NLS-1$
newLine(strb);
for (final String line : getSortedLines(live, total)) {
strb.append(line);
newLine(strb);
}
appendNTimes(STAR, 2 * NOS + HEADER.length(), strb);
return strb.toString();
}
///// Helping Methods
private static final String DELIMITER = "\t"; //$NON-NLS-1$
private static final String LINE_FORMAT = "% 5d" + DELIMITER + "% 5d" + DELIMITER + "%s"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
private static List<String> getSortedLines(final ObjectCounter<Class<?>> live, final ObjectCounter<Class<?>> total) {
final List<String> result = new ArrayList<String>();
for (final Class<?> clazz : live) {
result.add(String.format(LINE_FORMAT, live.getCount(clazz), total.getCount(clazz), clazz.getName()));
}
Collections.sort(result, new Comparator<String>() {
public int compare(final String o1, final String o2) {
final Integer i1 = Integer.valueOf(o1.split(DELIMITER)[0].trim());
final Integer i2 = Integer.valueOf(o2.split(DELIMITER)[0].trim());
return i2.compareTo(i1);
}
});
return result;
}
private static void newLine(final StringBuilder strb) {
strb.append("\n"); //$NON-NLS-1$
}
private static void appendNTimes(final String str, final int n, final StringBuilder strb) {
for (int i = 0; i < n; i++) {
strb.append(str);
}
}
}